diff --git a/docs/CHEATSHEET.md b/docs/CHEATSHEET.md
index a85ec39..ab9f51f 100644
--- a/docs/CHEATSHEET.md
+++ b/docs/CHEATSHEET.md
@@ -48,6 +48,11 @@ $article->setMetadata(
->setThumbnailURL('https://example.com/thumb.jpg')
->setContentGenerationType('none') // 'none' or 'AI'
->setTransparentToolbar(true) // For immersive headers
+ ->setIssueFromArray([ // For magazines/periodicals
+ 'issueIdentifier' => 'issue-2024-01',
+ 'issueDate' => '2024-01-15',
+ 'issueName' => 'January 2024'
+ ])
);
```
@@ -79,10 +84,16 @@ Photo::fromUrl('https://...');
Photo::fromBundle('image.jpg');
Photo::fromUrl('...')->setCaption('...')->setAccessibilityCaption('...');
+Image::fromUrl('https://...'); // Generic image
(new Figure())->setUrl('...')->setCaption('...');
+Portrait::fromUrl('https://...'); // Portrait orientation
+Logo::fromUrl('https://...'); // Publication logo
(new Video())->setUrl('...');
(new Audio())->setUrl('...');
(new Gallery())->addItem($figure1)->addItem($figure2);
+(new Mosaic())->addItem($figure1); // Mosaic layout
+new Music(); // Apple Music embed
+new Podcast(); // Podcast episode
ARKit::fromUrl('https://example.com/model.usdz');
```
@@ -114,10 +125,12 @@ new FlexibleSpacer(); // Flexible spacing
new LinkButton('Click Here', 'https://...');
new ArticleLink::fromArticleId('article-id');
new Map(latitude: 51.5074, longitude: -0.1278);
+new Place(latitude: 51.5074, longitude: -0.1278, caption: 'London');
new DataTable();
new HTMLTable('
');
new BannerAdvertisement();
new MediumRectangleAdvertisement();
+new ReplicaAdvertisement(); // Print replica ad
```
---
@@ -155,6 +168,16 @@ $style->setDropCapStyle([
]);
```
+### Inline Text Styles
+
+```php
+// Style portions of text within a component
+$body->setInlineTextStyles([
+ ['rangeStart' => 0, 'rangeLength' => 5, 'textStyle' => 'bold-style'],
+ ['rangeStart' => 10, 'rangeLength' => 8, 'textStyle' => 'link-style']
+]);
+```
+
---
## Layouts
@@ -221,14 +244,18 @@ $container->setStyle([
use TomGould\AppleNews\Document\Animations\*;
use TomGould\AppleNews\Document\Behaviors\*;
-// Animations
-$component->setAnimationObject(FadeInAnimation::standard());
-$component->setAnimationObject(MoveInAnimation::fromLeft());
-$component->setAnimationObject(ScaleFadeAnimation::subtle());
-
-// Behaviors
-$component->setBehaviorObject(Parallax::withFactor(0.5));
-$component->setBehaviorObject(Springy::create());
+// Animations (all from Apple News Format)
+$component->setAnimationObject(AppearAnimation::create()); // Generic appear
+$component->setAnimationObject(FadeInAnimation::standard()); // Fade in
+$component->setAnimationObject(MoveInAnimation::fromLeft()); // Move from direction
+$component->setAnimationObject(ScaleFadeAnimation::subtle()); // Scale + fade
+
+// Behaviors (all from Apple News Format)
+$component->setBehaviorObject(Parallax::withFactor(0.5)); // Parallax scroll
+$component->setBehaviorObject(BackgroundParallax::withFactor(0.8));
+$component->setBehaviorObject(Springy::create()); // Spring physics
+$component->setBehaviorObject(Motion::create()); // Gyroscope
+$component->setBehaviorObject(BackgroundMotion::create()); // Gyro for backgrounds
// Header scenes
use TomGould\AppleNews\Document\Scenes\*;
diff --git a/docs/COOKBOOK.md b/docs/COOKBOOK.md
index a7c2c64..39f2b6f 100644
--- a/docs/COOKBOOK.md
+++ b/docs/COOKBOOK.md
@@ -305,19 +305,20 @@ $article->addComponent(
### Media Components
-| Component | Factory Methods |
-|-----------|-----------------|
-| `Photo` | `fromUrl()`, `fromBundle()` |
-| `Figure` | `fromUrl()`, `fromBundle()` |
-| `Portrait` | - |
-| `Logo` | - |
-| `Gallery` | `addItem()` |
-| `Mosaic` | - |
-| `Video` | `fromUrl()`, `fromBundle()` |
-| `Audio` | `fromUrl()`, `fromBundle()` |
-| `Music` | - |
-| `Podcast` | - |
-| `ARKit` | `fromUrl()`, `fromBundle()` |
+| Component | Factory Methods | Notes |
+|-----------|-----------------|-------|
+| `Photo` | `fromUrl()`, `fromBundle()` | Single image |
+| `Image` | `fromUrl()`, `fromBundle()` | Generic image (alias) |
+| `Figure` | `fromUrl()`, `fromBundle()` | Image with caption |
+| `Portrait` | `fromUrl()`, `fromBundle()` | Portrait-oriented image |
+| `Logo` | `fromUrl()`, `fromBundle()` | Publication logo |
+| `Gallery` | `addItem()` | Horizontal image gallery |
+| `Mosaic` | `addItem()` | Mosaic image layout |
+| `Video` | `fromUrl()`, `fromBundle()` | Native video player |
+| `Audio` | `fromUrl()`, `fromBundle()` | Audio player |
+| `Music` | - | Apple Music integration |
+| `Podcast` | - | Podcast episode embed |
+| `ARKit` | `fromUrl()`, `fromBundle()` | AR Quick Look 3D models |
### Social Embeds
@@ -343,15 +344,17 @@ $article->addComponent(
### Data & Interactive
-| Component | Key Methods |
-|-----------|-------------|
-| `DataTable` | `setData()`, `setSortBy()` |
-| `HTMLTable` | `fromHtml()` |
-| `Map` | constructor(lat, lng) |
-| `LinkButton` | constructor(text, url) |
-| `ArticleLink` | `fromArticleId()` |
-| `BannerAdvertisement` | - |
-| `MediumRectangleAdvertisement` | - |
+| Component | Key Methods | Notes |
+|-----------|-------------|-------|
+| `DataTable` | `setData()`, `setSortBy()` | Interactive sortable table |
+| `HTMLTable` | `fromHtml()` | HTML-based table |
+| `Map` | constructor(lat, lng) | Interactive Apple Maps |
+| `Place` | constructor(lat, lng, caption) | Location marker for Map |
+| `LinkButton` | constructor(text, url) | Call-to-action button |
+| `ArticleLink` | `fromArticleId()` | Link to another article |
+| `BannerAdvertisement` | - | Banner ad slot |
+| `MediumRectangleAdvertisement` | - | MREC ad slot (300x250) |
+| `ReplicaAdvertisement` | - | Print replica ad slot |
---
@@ -474,6 +477,36 @@ $titleStyle = (new ComponentTextStyle())
]);
```
+### Inline Text Styles
+
+Apply different styles to portions of text within a component:
+
+```php
+// Define styles for different text ranges
+$body = new Body('Welcome to our exclusive report on the latest developments.');
+
+$body->setInlineTextStyles([
+ [
+ 'rangeStart' => 0,
+ 'rangeLength' => 7, // "Welcome"
+ 'textStyle' => 'bold-style'
+ ],
+ [
+ 'rangeStart' => 15,
+ 'rangeLength' => 9, // "exclusive"
+ 'textStyle' => 'emphasis-style'
+ ]
+]);
+
+// Register the styles first
+$article->addComponentTextStyle('bold-style',
+ (new ComponentTextStyle())->setFontWeight('bold')
+);
+$article->addComponentTextStyle('emphasis-style',
+ (new ComponentTextStyle())->setFontStyle('italic')->setTextColor('#007AFF')
+);
+```
+
---
## Dark Mode Support
@@ -566,25 +599,49 @@ $videoFill = (new VideoFill('https://example.com/bg-video.mp4'))
### Animations
+All animations from Apple News Format are supported:
+
```php
use TomGould\AppleNews\Document\Animations\*;
+// Appear animation (generic)
+$component->setAnimationObject(AppearAnimation::create());
+
+// Fade in animation
$component->setAnimationObject(FadeInAnimation::standard());
+$component->setAnimationObject(FadeInAnimation::fromTransparent());
+$component->setAnimationObject(FadeInAnimation::withDelay(0.3));
+
+// Move in animation
$component->setAnimationObject(MoveInAnimation::fromLeft());
$component->setAnimationObject(MoveInAnimation::fromRight());
+$component->setAnimationObject(MoveInAnimation::fromBottom());
+
+// Scale fade animation
$component->setAnimationObject(ScaleFadeAnimation::subtle());
-$component->setAnimationObject(FadeInAnimation::withDelay(0.3));
```
### Behaviors
+All behaviors from Apple News Format are supported:
+
```php
use TomGould\AppleNews\Document\Behaviors\*;
-$photo->setBehaviorObject(Parallax::withFactor(0.5));
+// Parallax scrolling
+$photo->setBehaviorObject(Parallax::withFactor(0.5)); // 0-1 factor
+
+// Background parallax (for fills)
$header->setBehaviorObject(BackgroundParallax::withFactor(0.8));
+
+// Spring physics
$component->setBehaviorObject(Springy::create());
+
+// Motion (gyroscope-based movement)
$component->setBehaviorObject(Motion::create());
+
+// Background motion (gyroscope for backgrounds)
+$component->setBehaviorObject(BackgroundMotion::create());
```
### Scenes (Header Effects)
@@ -632,6 +689,44 @@ $article->setAutoplacement([
---
+## Magazine/Periodical Metadata
+
+For magazine and periodical publishers, use the `Issue` class to associate articles with specific issues:
+
+```php
+use TomGould\AppleNews\Document\Issue;
+
+$article->setMetadata(
+ (new Metadata())
+ ->addAuthor('Editorial Team')
+ ->setExcerpt('Cover story for our January issue')
+ ->setDatePublished(new DateTime('2024-01-15'))
+ ->setIssue(
+ (new Issue())
+ ->setIssueIdentifier('issue-2024-01')
+ ->setIssueDate('2024-01-15')
+ ->setIssueName('January 2024')
+ )
+);
+
+// Or using array syntax
+$article->setMetadata(
+ (new Metadata())
+ ->setIssueFromArray([
+ 'issueIdentifier' => 'issue-2024-01',
+ 'issueDate' => '2024-01-15',
+ 'issueName' => 'January 2024'
+ ])
+);
+```
+
+This enables:
+- Issue-based navigation in Apple News
+- Grouping of articles by issue
+- Historical archive browsing
+
+---
+
## API Operations
### Create Article with Assets