@krizaka/ui 3.37.0 → 3.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/blocks.css +36 -36
  2. package/dist/chip-link.js +1 -1
  3. package/dist/chip-row.js +1 -1
  4. package/dist/{chunk-IANSFIVC.js → chunk-7JFHTPI3.js} +13 -3
  5. package/dist/chunk-7JFHTPI3.js.map +1 -0
  6. package/dist/{chunk-RE5WJ4QP.js → chunk-ADRUEPYC.js} +4 -4
  7. package/dist/chunk-ADRUEPYC.js.map +1 -0
  8. package/dist/{chunk-BTTDIVVJ.js → chunk-F2UZ2WWL.js} +2 -2
  9. package/dist/chunk-F2UZ2WWL.js.map +1 -0
  10. package/dist/image-cropper.js +1 -1
  11. package/dist/kanban.js +1 -1
  12. package/dist/kanban.js.map +1 -1
  13. package/dist/landing-page.js +1 -6
  14. package/dist/landing-page.js.map +1 -1
  15. package/dist/map.js +2 -2
  16. package/dist/map.js.map +1 -1
  17. package/dist/motion.css +3 -3
  18. package/dist/native/vertical-video.js +1 -1
  19. package/dist/native/vertical-video.js.map +1 -1
  20. package/dist/native.d.ts +1 -1
  21. package/dist/native.js +11 -11
  22. package/dist/native.js.map +1 -1
  23. package/dist/nav-bar.d.ts +1 -1
  24. package/dist/nav-bar.js +1 -1
  25. package/dist/photo-grid.js +1 -1
  26. package/dist/photo-grid.js.map +1 -1
  27. package/dist/product-page.js +1 -6
  28. package/dist/product-page.js.map +1 -1
  29. package/dist/site-footer.d.ts +5 -17
  30. package/dist/site-footer.js +33 -29
  31. package/dist/site-footer.js.map +1 -1
  32. package/dist/{sites-B4sYlfPQ.d.ts → sites-inztN_Bv.d.ts} +8 -0
  33. package/dist/sites.d.ts +11 -1
  34. package/dist/sites.js +12 -2
  35. package/dist/sites.js.map +1 -1
  36. package/dist/slider.js +3 -3
  37. package/dist/slider.js.map +1 -1
  38. package/dist/step-showcase.js +1 -1
  39. package/dist/step-showcase.js.map +1 -1
  40. package/dist/story.css +3 -3
  41. package/dist/video-player.js +1 -1
  42. package/dist/video-trimmer.js +1 -1
  43. package/dist/video-trimmer.js.map +1 -1
  44. package/package.json +3 -3
  45. package/registry/chip-link.json +1 -1
  46. package/registry/examples/site-footer/company.js +0 -4
  47. package/registry/examples/site-footer/company.tsx +3 -7
  48. package/registry/index.json +7 -7
  49. package/registry/kanban.json +1 -1
  50. package/registry/landing-page.json +1 -1
  51. package/registry/map.json +2 -2
  52. package/registry/nav-bar.json +1 -1
  53. package/registry/photo-grid.json +1 -1
  54. package/registry/product-page.json +1 -1
  55. package/registry/rail-nav.json +1 -1
  56. package/registry/site-footer.json +10 -10
  57. package/registry/sites.json +2 -2
  58. package/registry/slider.json +1 -1
  59. package/registry/step-showcase.json +1 -1
  60. package/registry/video-trimmer.json +1 -1
  61. package/dist/chunk-BTTDIVVJ.js.map +0 -1
  62. package/dist/chunk-IANSFIVC.js.map +0 -1
  63. package/dist/chunk-RE5WJ4QP.js.map +0 -1
package/dist/motion.css CHANGED
@@ -162,7 +162,7 @@
162
162
  .maplibregl-canvas-container.maplibregl-interactive { cursor: grab; }
163
163
  .maplibregl-canvas-container.maplibregl-interactive:active { cursor: grabbing; }
164
164
  .maplibregl-marker { position: absolute; top: 0; left: 0; will-change: transform; }
165
- .kz-map-user { position: relative; width: 16px; height: 16px; border-radius: 9999px; background: var(--kz-accent); border: 3px solid var(--kz-surface-1); box-shadow: 0 1px 4px var(--kz-scrim); }
165
+ .kz-map-user { position: relative; width: 16px; height: 16px; border-radius: 9999px; background: var(--kz-accent); border: 3px solid var(--kz-surface-1); box-shadow: var(--kz-shadow-md); }
166
166
  .kz-map-user::after { content: ""; position: absolute; inset: -3px; border-radius: inherit; background: var(--kz-accent); opacity: 0.35; animation: kz-map-pulse 2s var(--kz-ease) infinite; }
167
167
  /* A pin dropped onto its place (`Marker drop={delay}`): falls from above, settles with a small bounce; once. */
168
168
  [data-kz-marker] > [data-drop] { animation: kz-map-drop 620ms cubic-bezier(0.34, 1.4, 0.64, 1) backwards; animation-delay: var(--kz-map-drop-delay, 0ms); }
@@ -174,7 +174,7 @@
174
174
  .kz-map-pulse[data-tone="soft"]::before, .kz-map-pulse[data-tone="soft"]::after { border-width: 1px; background: color-mix(in oklab, var(--kz-accent) 10%, transparent); }
175
175
  @keyframes kz-map-heat { from { transform: scale(0.15); opacity: 0.9; } to { transform: scale(1); opacity: 0; } }
176
176
  /* The courier of a `Route`: an accent dot with a ring, moved along the line by the component. */
177
- .kz-map-courier { width: 14px; height: 14px; border-radius: 9999px; background: var(--kz-accent); border: 3px solid var(--kz-surface-1); box-shadow: 0 0 0 4px color-mix(in oklab, var(--kz-accent) 30%, transparent), 0 2px 6px var(--kz-scrim); }
177
+ .kz-map-courier { width: 14px; height: 14px; border-radius: 9999px; background: var(--kz-accent); border: 3px solid var(--kz-surface-1); box-shadow: 0 0 0 4px color-mix(in oklab, var(--kz-accent) 30%, transparent); }
178
178
  @keyframes kz-map-pulse { from { transform: scale(1); opacity: 0.4; } to { transform: scale(3.2); opacity: 0; } }
179
179
 
180
180
  /* Section backdrop (SectionBackdrop): the brand's section gradient (--kz-brand-gradient-*), sections that glide from
@@ -247,7 +247,7 @@ svg[data-kz-icon="ExternalIcon"] {
247
247
  /* A figure that climbs (NumberTicker): an invisible copy of the final value shares the grid cell and holds the width. */
248
248
  .kz-count {
249
249
  display: inline-grid;
250
- font-variant-numeric: tabular-nums;
250
+ font-variant-numeric: var(--kz-figures, lining-nums tabular-nums);
251
251
  }
252
252
  .kz-count > * {
253
253
  grid-area: 1 / 1;
@@ -147,7 +147,7 @@ var styles = StyleSheet.create({
147
147
  rail: { position: "absolute", right: 8, bottom: 20, alignItems: "center", gap: 12 },
148
148
  railItem: { alignItems: "center", gap: 2 },
149
149
  railButton: { width: 44, height: 44, borderRadius: 22, alignItems: "center", justifyContent: "center" },
150
- count: { fontVariant: ["tabular-nums"], fontWeight: "600" },
150
+ count: { fontVariant: ["lining-nums", "tabular-nums"], fontWeight: "600" },
151
151
  follow: { position: "absolute", bottom: -10, alignSelf: "center", width: 22, height: 22, borderRadius: 11, alignItems: "center", justifyContent: "center", overflow: "hidden" },
152
152
  caption: { position: "absolute", left: 12, right: 76, bottom: 16, gap: 6 },
153
153
  nameRow: { flexDirection: "row", alignItems: "center", gap: 6 },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/native/vertical-video.tsx"],"sourcesContent":["// @krizaka/ui/native/vertical-video — its own entry (it plays video on expo-video, an optional peer). A 9:16 clip filling\n// its frame, the action rail on the right (avatar + follow, like, comments, share, a slot for the product's tip), the\n// creator's caption bottom-left, a progress hairline; `ShortFeed` pages them vertically and plays the one in view.\n// Over the picture everything reads on the theme's invariant `scrim` / `textOnMedia`.\nimport { formatCompact } from \"@krizaka/intl\";\nimport { Avatar, Txt, useTheme, VerifiedBadge } from \"@krizaka/ui/native\";\nimport { VideoPlayer } from \"@krizaka/ui/native/video-player\";\nimport * as React from \"react\";\nimport { FlatList, Image,Pressable, type StyleProp, StyleSheet, View, type ViewStyle, type ViewToken } from \"react-native\";\nimport Svg, { Path } from \"react-native-svg\";\n\nexport interface VerticalVideoLabels {\n play: string;\n pause: string;\n like: string;\n comment: string;\n share: string;\n more: string;\n /** \"Follow {name}\". */\n follow: string;\n /** \"Following {name}\". */\n following: string;\n expand: string;\n collapse: string;\n progress: string;\n /** The rail's name (\"Actions\"). */\n actions: string;\n}\n\nexport const verticalVideoLabels: VerticalVideoLabels = {\n play: \"Play\",\n pause: \"Pause\",\n like: \"Like\",\n comment: \"Comments\",\n share: \"Share\",\n more: \"More\",\n follow: \"Follow {name}\",\n following: \"Following {name}\",\n expand: \"More\",\n collapse: \"Less\",\n progress: \"Progress\",\n actions: \"Actions\",\n};\n\nexport type VerticalVideoProps = {\n /** The video's accessible name (\"Video: Night shoot, part 2\"), passed translated. */\n title: string;\n /** The clip's address (MP4 or HLS). Absent, the poster alone shows. */\n uri?: string;\n /** The picture until the first frame. */\n posterUri?: string;\n /** Plays while `true` (a `ShortFeed` passes it for the slide in view). Default `true`. */\n active?: boolean;\n /** Who made it: name, portrait, the seal's words. */\n creator: { name: string; avatarUri?: string; verifiedLabel?: string };\n /** A pill beside the name (\"AI-GENERATED\"). */\n disclosure?: string;\n /** The caption, two lines until expanded. */\n caption?: string;\n /** Tags after the caption (without `#`). */\n tags?: readonly string[];\n /** The sound or credit line. */\n credit?: string;\n /** The like count, compact in `locale`. */\n likes?: number;\n /** The comment count. */\n comments?: number;\n /** The share count. */\n shares?: number;\n /** Whether the viewer likes it. */\n liked?: boolean;\n /** Whether the viewer follows the creator. */\n following?: boolean;\n /** The viewer likes or unlikes. */\n onLike?: (liked: boolean) => void;\n /** Opens the comments. */\n onComment?: () => void;\n /** Opens the share sheet. */\n onShare?: () => void;\n /** Follows or unfollows; without it the avatar has no \"+\". */\n onFollow?: (following: boolean) => void;\n /** The \"more\" action; without it the button is not drawn. */\n onMore?: () => void;\n /** The product's own action on the rail (a tip, an unlock): a named, 44 pt button of yours. */\n tipSlot?: React.ReactNode;\n /** Top left over the picture: a chip (an auction's time left). */\n topStart?: React.ReactNode;\n /** Above the caption: a goal gauge. */\n aboveCaption?: React.ReactNode;\n /** The locale of the counts. Default `en`. */\n locale?: string;\n /** Every word, passed translated. */\n labels?: Partial<VerticalVideoLabels>;\n /** Styles merged last, on the frame. */\n style?: StyleProp<ViewStyle>;\n};\n\nconst HEART = \"M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z\";\nconst COMMENT = \"M4 5h16v11H9l-5 4z\";\nconst SHARE = \"M4 12v7h16v-7M12 3v12M7 8l5-5 5 5\";\nconst MORE = \"M5 12h.01M12 12h.01M19 12h.01\";\n\nfunction Glyph({ d, color, filled }: { d: string; color: string; filled?: boolean }) {\n return (\n <Svg width={24} height={24} viewBox=\"0 0 24 24\" fill={filled ? color : \"none\"} stroke={color} strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <Path d={d} />\n </Svg>\n );\n}\n\nfunction RailButton({ label, count, pressed, onPress, children }: { label: string; count?: string | undefined; pressed?: boolean | undefined; onPress?: (() => void) | undefined; children: React.ReactNode }) {\n const { theme } = useTheme();\n return (\n <View style={styles.railItem}>\n <Pressable role=\"button\" aria-label={label} aria-pressed={pressed} onPress={onPress} hitSlop={4} style={[styles.railButton, { backgroundColor: theme.scrim }]}>\n {children}\n </Pressable>\n {count !== undefined ? (\n <Txt variant=\"caption\" tone=\"onMedia\" style={styles.count}>\n {count}\n </Txt>\n ) : null}\n </View>\n );\n}\n\n/** One short video: 9:16, the rail of actions on the right, the creator's caption bottom-left. */\nexport function VerticalVideo({\n title,\n uri,\n posterUri,\n active = true,\n creator,\n disclosure,\n caption,\n tags = [],\n credit,\n likes,\n comments,\n shares,\n liked = false,\n following = false,\n onLike,\n onComment,\n onShare,\n onFollow,\n onMore,\n tipSlot,\n topStart,\n aboveCaption,\n locale = \"en\",\n labels: custom,\n style,\n}: VerticalVideoProps) {\n const { theme } = useTheme();\n const labels = { ...verticalVideoLabels, ...custom };\n const [open, setOpen] = React.useState(false);\n const [paused, setPaused] = React.useState(false);\n const count = (n?: number) => (n === undefined ? undefined : formatCompact(n, { locale }));\n const on = theme.textOnMedia;\n return (\n <View role=\"group\" aria-label={title} style={[styles.frame, { backgroundColor: theme.media }, style]}>\n {uri ? (\n <VideoPlayer source={{ uri }} title={title} aspectRatio={9 / 16} contentFit=\"cover\" nativeControls={false} fullscreen={false} autoPlay loop muted paused={!active || paused} style={StyleSheet.absoluteFill} {...(posterUri ? { poster: { uri: posterUri } } : {})} />\n ) : posterUri ? (\n <Image source={{ uri: posterUri }} aria-hidden resizeMode=\"cover\" style={StyleSheet.absoluteFill} />\n ) : null}\n <Pressable role=\"button\" aria-label={paused ? labels.play : labels.pause} onPress={() => setPaused((p) => !p)} onLongPress={() => onLike?.(!liked)} style={StyleSheet.absoluteFill} />\n <View pointerEvents=\"none\" style={[styles.shade, { backgroundColor: theme.scrim }]} />\n {topStart ? <View style={styles.topStart}>{topStart}</View> : null}\n\n <View role=\"group\" aria-label={labels.actions} style={styles.rail}>\n <View>\n <Avatar alt={creator.name} {...(creator.avatarUri ? { src: creator.avatarUri } : {})} size=\"md\" />\n {onFollow ? (\n <Pressable\n role=\"button\"\n aria-label={(following ? labels.following : labels.follow).replace(\"{name}\", creator.name)}\n aria-pressed={following}\n onPress={() => onFollow(!following)}\n hitSlop={12}\n style={[styles.follow, { backgroundColor: following ? theme.surface2 : theme.accent }]}\n >\n <Glyph d={following ? \"M5 12l5 5 9-10\" : \"M12 5v14M5 12h14\"} color={following ? theme.textPrimary : theme.onAccent} />\n </Pressable>\n ) : null}\n </View>\n <RailButton label={labels.like} count={count(likes)} pressed={liked} onPress={() => onLike?.(!liked)}>\n <Glyph d={HEART} color={liked ? theme.accent : on} filled={liked} />\n </RailButton>\n <RailButton label={labels.comment} count={count(comments)} onPress={onComment}>\n <Glyph d={COMMENT} color={on} />\n </RailButton>\n <RailButton label={labels.share} count={count(shares)} onPress={onShare}>\n <Glyph d={SHARE} color={on} />\n </RailButton>\n {tipSlot}\n {onMore ? (\n <RailButton label={labels.more} onPress={onMore}>\n <Glyph d={MORE} color={on} />\n </RailButton>\n ) : null}\n </View>\n\n <View style={styles.caption}>\n {aboveCaption}\n <View style={styles.nameRow}>\n <Txt variant=\"label\" tone=\"onMedia\">\n {creator.name}\n </Txt>\n {creator.verifiedLabel ? <VerifiedBadge label={creator.verifiedLabel} on=\"media\" size={14} /> : null}\n {disclosure ? (\n <View style={[styles.pill, { backgroundColor: theme.scrim }]}>\n <Txt variant=\"caption\" tone=\"onMedia\" style={styles.pillText}>\n {disclosure.toUpperCase()}\n </Txt>\n </View>\n ) : null}\n </View>\n {caption ? (\n <Txt tone=\"onMedia\" numberOfLines={open ? undefined : 2}>\n {caption}\n {tags.length > 0 ? ` ${tags.map((tag) => `#${tag}`).join(\" \")}` : \"\"}\n </Txt>\n ) : null}\n {caption && caption.length > 90 ? (\n <Pressable role=\"button\" aria-label={open ? labels.collapse : labels.expand} aria-expanded={open} onPress={() => setOpen((v) => !v)} hitSlop={10}>\n <Txt variant=\"caption\" tone=\"onMedia\" style={styles.underline}>\n {open ? labels.collapse : labels.expand}\n </Txt>\n </Pressable>\n ) : null}\n {credit ? (\n <Txt variant=\"caption\" tone=\"onMedia\">\n {credit}\n </Txt>\n ) : null}\n </View>\n </View>\n );\n}\n\nexport type ShortFeedProps<T> = {\n /** The feed's accessible name (\"Videos\"). */\n label: string;\n /** The videos, in order. */\n items: readonly T[];\n /** A stable key for an item. */\n getId: (item: T) => string;\n /** One slide: `active` is true for the one in view. */\n renderItem: (item: T, state: { active: boolean; index: number }) => React.ReactElement;\n /** The page's height in points (the feed's own height; one slide per page). */\n height: number;\n /** Called when the slide in view changes. */\n onActiveChange?: (index: number, item: T) => void;\n /** Styles merged last. */\n style?: StyleProp<ViewStyle>;\n};\n\n/** A vertical paging feed: one video per screen, the one in view plays, the others pause. */\nexport function ShortFeed<T>({ label, items, getId, renderItem, height, onActiveChange, style }: ShortFeedProps<T>) {\n const [active, setActive] = React.useState(0);\n // FlatList wants one stable callback for its whole life.\n const [onViewable] = React.useState(() => ({ viewableItems }: { viewableItems: ViewToken[] }) => {\n const first = viewableItems.find((v) => v.isViewable && typeof v.index === \"number\");\n if (first && typeof first.index === \"number\") setActive(first.index);\n });\n React.useEffect(() => {\n const item = items[active];\n if (item !== undefined) onActiveChange?.(active, item);\n // Only a change of the slide in view is an event.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [active]);\n return (\n <View role=\"list\" aria-label={label} style={[{ height }, style]}>\n <FlatList\n data={items as T[]}\n keyExtractor={getId}\n pagingEnabled\n showsVerticalScrollIndicator={false}\n snapToInterval={height}\n decelerationRate=\"fast\"\n getItemLayout={(_, index) => ({ length: height, offset: height * index, index })}\n windowSize={3}\n initialNumToRender={2}\n viewabilityConfig={{ itemVisiblePercentThreshold: 60 }}\n onViewableItemsChanged={onViewable}\n extraData={active}\n style={{ height }}\n renderItem={({ item, index }) => <View style={{ height }}>{renderItem(item, { active: index === active, index })}</View>}\n />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n frame: { width: \"100%\", aspectRatio: 9 / 16, overflow: \"hidden\" },\n shade: { position: \"absolute\", left: 0, right: 0, bottom: 0, height: \"30%\", opacity: 0.55 },\n topStart: { position: \"absolute\", left: 12, top: 12 },\n rail: { position: \"absolute\", right: 8, bottom: 20, alignItems: \"center\", gap: 12 },\n railItem: { alignItems: \"center\", gap: 2 },\n railButton: { width: 44, height: 44, borderRadius: 22, alignItems: \"center\", justifyContent: \"center\" },\n count: { fontVariant: [\"tabular-nums\"], fontWeight: \"600\" },\n follow: { position: \"absolute\", bottom: -10, alignSelf: \"center\", width: 22, height: 22, borderRadius: 11, alignItems: \"center\", justifyContent: \"center\", overflow: \"hidden\" },\n caption: { position: \"absolute\", left: 12, right: 76, bottom: 16, gap: 6 },\n nameRow: { flexDirection: \"row\", alignItems: \"center\", gap: 6 },\n pill: { paddingHorizontal: 8, paddingVertical: 2, borderRadius: 999 },\n pillText: { fontWeight: \"700\", letterSpacing: 0.4 },\n underline: { textDecorationLine: \"underline\", fontWeight: \"600\" },\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/native/vertical-video.tsx"],"sourcesContent":["// @krizaka/ui/native/vertical-video — its own entry (it plays video on expo-video, an optional peer). A 9:16 clip filling\n// its frame, the action rail on the right (avatar + follow, like, comments, share, a slot for the product's tip), the\n// creator's caption bottom-left, a progress hairline; `ShortFeed` pages them vertically and plays the one in view.\n// Over the picture everything reads on the theme's invariant `scrim` / `textOnMedia`.\nimport { formatCompact } from \"@krizaka/intl\";\nimport { Avatar, Txt, useTheme, VerifiedBadge } from \"@krizaka/ui/native\";\nimport { VideoPlayer } from \"@krizaka/ui/native/video-player\";\nimport * as React from \"react\";\nimport { FlatList, Image,Pressable, type StyleProp, StyleSheet, View, type ViewStyle, type ViewToken } from \"react-native\";\nimport Svg, { Path } from \"react-native-svg\";\n\nexport interface VerticalVideoLabels {\n play: string;\n pause: string;\n like: string;\n comment: string;\n share: string;\n more: string;\n /** \"Follow {name}\". */\n follow: string;\n /** \"Following {name}\". */\n following: string;\n expand: string;\n collapse: string;\n progress: string;\n /** The rail's name (\"Actions\"). */\n actions: string;\n}\n\nexport const verticalVideoLabels: VerticalVideoLabels = {\n play: \"Play\",\n pause: \"Pause\",\n like: \"Like\",\n comment: \"Comments\",\n share: \"Share\",\n more: \"More\",\n follow: \"Follow {name}\",\n following: \"Following {name}\",\n expand: \"More\",\n collapse: \"Less\",\n progress: \"Progress\",\n actions: \"Actions\",\n};\n\nexport type VerticalVideoProps = {\n /** The video's accessible name (\"Video: Night shoot, part 2\"), passed translated. */\n title: string;\n /** The clip's address (MP4 or HLS). Absent, the poster alone shows. */\n uri?: string;\n /** The picture until the first frame. */\n posterUri?: string;\n /** Plays while `true` (a `ShortFeed` passes it for the slide in view). Default `true`. */\n active?: boolean;\n /** Who made it: name, portrait, the seal's words. */\n creator: { name: string; avatarUri?: string; verifiedLabel?: string };\n /** A pill beside the name (\"AI-GENERATED\"). */\n disclosure?: string;\n /** The caption, two lines until expanded. */\n caption?: string;\n /** Tags after the caption (without `#`). */\n tags?: readonly string[];\n /** The sound or credit line. */\n credit?: string;\n /** The like count, compact in `locale`. */\n likes?: number;\n /** The comment count. */\n comments?: number;\n /** The share count. */\n shares?: number;\n /** Whether the viewer likes it. */\n liked?: boolean;\n /** Whether the viewer follows the creator. */\n following?: boolean;\n /** The viewer likes or unlikes. */\n onLike?: (liked: boolean) => void;\n /** Opens the comments. */\n onComment?: () => void;\n /** Opens the share sheet. */\n onShare?: () => void;\n /** Follows or unfollows; without it the avatar has no \"+\". */\n onFollow?: (following: boolean) => void;\n /** The \"more\" action; without it the button is not drawn. */\n onMore?: () => void;\n /** The product's own action on the rail (a tip, an unlock): a named, 44 pt button of yours. */\n tipSlot?: React.ReactNode;\n /** Top left over the picture: a chip (an auction's time left). */\n topStart?: React.ReactNode;\n /** Above the caption: a goal gauge. */\n aboveCaption?: React.ReactNode;\n /** The locale of the counts. Default `en`. */\n locale?: string;\n /** Every word, passed translated. */\n labels?: Partial<VerticalVideoLabels>;\n /** Styles merged last, on the frame. */\n style?: StyleProp<ViewStyle>;\n};\n\nconst HEART = \"M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z\";\nconst COMMENT = \"M4 5h16v11H9l-5 4z\";\nconst SHARE = \"M4 12v7h16v-7M12 3v12M7 8l5-5 5 5\";\nconst MORE = \"M5 12h.01M12 12h.01M19 12h.01\";\n\nfunction Glyph({ d, color, filled }: { d: string; color: string; filled?: boolean }) {\n return (\n <Svg width={24} height={24} viewBox=\"0 0 24 24\" fill={filled ? color : \"none\"} stroke={color} strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <Path d={d} />\n </Svg>\n );\n}\n\nfunction RailButton({ label, count, pressed, onPress, children }: { label: string; count?: string | undefined; pressed?: boolean | undefined; onPress?: (() => void) | undefined; children: React.ReactNode }) {\n const { theme } = useTheme();\n return (\n <View style={styles.railItem}>\n <Pressable role=\"button\" aria-label={label} aria-pressed={pressed} onPress={onPress} hitSlop={4} style={[styles.railButton, { backgroundColor: theme.scrim }]}>\n {children}\n </Pressable>\n {count !== undefined ? (\n <Txt variant=\"caption\" tone=\"onMedia\" style={styles.count}>\n {count}\n </Txt>\n ) : null}\n </View>\n );\n}\n\n/** One short video: 9:16, the rail of actions on the right, the creator's caption bottom-left. */\nexport function VerticalVideo({\n title,\n uri,\n posterUri,\n active = true,\n creator,\n disclosure,\n caption,\n tags = [],\n credit,\n likes,\n comments,\n shares,\n liked = false,\n following = false,\n onLike,\n onComment,\n onShare,\n onFollow,\n onMore,\n tipSlot,\n topStart,\n aboveCaption,\n locale = \"en\",\n labels: custom,\n style,\n}: VerticalVideoProps) {\n const { theme } = useTheme();\n const labels = { ...verticalVideoLabels, ...custom };\n const [open, setOpen] = React.useState(false);\n const [paused, setPaused] = React.useState(false);\n const count = (n?: number) => (n === undefined ? undefined : formatCompact(n, { locale }));\n const on = theme.textOnMedia;\n return (\n <View role=\"group\" aria-label={title} style={[styles.frame, { backgroundColor: theme.media }, style]}>\n {uri ? (\n <VideoPlayer source={{ uri }} title={title} aspectRatio={9 / 16} contentFit=\"cover\" nativeControls={false} fullscreen={false} autoPlay loop muted paused={!active || paused} style={StyleSheet.absoluteFill} {...(posterUri ? { poster: { uri: posterUri } } : {})} />\n ) : posterUri ? (\n <Image source={{ uri: posterUri }} aria-hidden resizeMode=\"cover\" style={StyleSheet.absoluteFill} />\n ) : null}\n <Pressable role=\"button\" aria-label={paused ? labels.play : labels.pause} onPress={() => setPaused((p) => !p)} onLongPress={() => onLike?.(!liked)} style={StyleSheet.absoluteFill} />\n <View pointerEvents=\"none\" style={[styles.shade, { backgroundColor: theme.scrim }]} />\n {topStart ? <View style={styles.topStart}>{topStart}</View> : null}\n\n <View role=\"group\" aria-label={labels.actions} style={styles.rail}>\n <View>\n <Avatar alt={creator.name} {...(creator.avatarUri ? { src: creator.avatarUri } : {})} size=\"md\" />\n {onFollow ? (\n <Pressable\n role=\"button\"\n aria-label={(following ? labels.following : labels.follow).replace(\"{name}\", creator.name)}\n aria-pressed={following}\n onPress={() => onFollow(!following)}\n hitSlop={12}\n style={[styles.follow, { backgroundColor: following ? theme.surface2 : theme.accent }]}\n >\n <Glyph d={following ? \"M5 12l5 5 9-10\" : \"M12 5v14M5 12h14\"} color={following ? theme.textPrimary : theme.onAccent} />\n </Pressable>\n ) : null}\n </View>\n <RailButton label={labels.like} count={count(likes)} pressed={liked} onPress={() => onLike?.(!liked)}>\n <Glyph d={HEART} color={liked ? theme.accent : on} filled={liked} />\n </RailButton>\n <RailButton label={labels.comment} count={count(comments)} onPress={onComment}>\n <Glyph d={COMMENT} color={on} />\n </RailButton>\n <RailButton label={labels.share} count={count(shares)} onPress={onShare}>\n <Glyph d={SHARE} color={on} />\n </RailButton>\n {tipSlot}\n {onMore ? (\n <RailButton label={labels.more} onPress={onMore}>\n <Glyph d={MORE} color={on} />\n </RailButton>\n ) : null}\n </View>\n\n <View style={styles.caption}>\n {aboveCaption}\n <View style={styles.nameRow}>\n <Txt variant=\"label\" tone=\"onMedia\">\n {creator.name}\n </Txt>\n {creator.verifiedLabel ? <VerifiedBadge label={creator.verifiedLabel} on=\"media\" size={14} /> : null}\n {disclosure ? (\n <View style={[styles.pill, { backgroundColor: theme.scrim }]}>\n <Txt variant=\"caption\" tone=\"onMedia\" style={styles.pillText}>\n {disclosure.toUpperCase()}\n </Txt>\n </View>\n ) : null}\n </View>\n {caption ? (\n <Txt tone=\"onMedia\" numberOfLines={open ? undefined : 2}>\n {caption}\n {tags.length > 0 ? ` ${tags.map((tag) => `#${tag}`).join(\" \")}` : \"\"}\n </Txt>\n ) : null}\n {caption && caption.length > 90 ? (\n <Pressable role=\"button\" aria-label={open ? labels.collapse : labels.expand} aria-expanded={open} onPress={() => setOpen((v) => !v)} hitSlop={10}>\n <Txt variant=\"caption\" tone=\"onMedia\" style={styles.underline}>\n {open ? labels.collapse : labels.expand}\n </Txt>\n </Pressable>\n ) : null}\n {credit ? (\n <Txt variant=\"caption\" tone=\"onMedia\">\n {credit}\n </Txt>\n ) : null}\n </View>\n </View>\n );\n}\n\nexport type ShortFeedProps<T> = {\n /** The feed's accessible name (\"Videos\"). */\n label: string;\n /** The videos, in order. */\n items: readonly T[];\n /** A stable key for an item. */\n getId: (item: T) => string;\n /** One slide: `active` is true for the one in view. */\n renderItem: (item: T, state: { active: boolean; index: number }) => React.ReactElement;\n /** The page's height in points (the feed's own height; one slide per page). */\n height: number;\n /** Called when the slide in view changes. */\n onActiveChange?: (index: number, item: T) => void;\n /** Styles merged last. */\n style?: StyleProp<ViewStyle>;\n};\n\n/** A vertical paging feed: one video per screen, the one in view plays, the others pause. */\nexport function ShortFeed<T>({ label, items, getId, renderItem, height, onActiveChange, style }: ShortFeedProps<T>) {\n const [active, setActive] = React.useState(0);\n // FlatList wants one stable callback for its whole life.\n const [onViewable] = React.useState(() => ({ viewableItems }: { viewableItems: ViewToken[] }) => {\n const first = viewableItems.find((v) => v.isViewable && typeof v.index === \"number\");\n if (first && typeof first.index === \"number\") setActive(first.index);\n });\n React.useEffect(() => {\n const item = items[active];\n if (item !== undefined) onActiveChange?.(active, item);\n // Only a change of the slide in view is an event.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [active]);\n return (\n <View role=\"list\" aria-label={label} style={[{ height }, style]}>\n <FlatList\n data={items as T[]}\n keyExtractor={getId}\n pagingEnabled\n showsVerticalScrollIndicator={false}\n snapToInterval={height}\n decelerationRate=\"fast\"\n getItemLayout={(_, index) => ({ length: height, offset: height * index, index })}\n windowSize={3}\n initialNumToRender={2}\n viewabilityConfig={{ itemVisiblePercentThreshold: 60 }}\n onViewableItemsChanged={onViewable}\n extraData={active}\n style={{ height }}\n renderItem={({ item, index }) => <View style={{ height }}>{renderItem(item, { active: index === active, index })}</View>}\n />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n frame: { width: \"100%\", aspectRatio: 9 / 16, overflow: \"hidden\" },\n shade: { position: \"absolute\", left: 0, right: 0, bottom: 0, height: \"30%\", opacity: 0.55 },\n topStart: { position: \"absolute\", left: 12, top: 12 },\n rail: { position: \"absolute\", right: 8, bottom: 20, alignItems: \"center\", gap: 12 },\n railItem: { alignItems: \"center\", gap: 2 },\n railButton: { width: 44, height: 44, borderRadius: 22, alignItems: \"center\", justifyContent: \"center\" },\n count: { fontVariant: [\"lining-nums\", \"tabular-nums\"], fontWeight: \"600\" },\n follow: { position: \"absolute\", bottom: -10, alignSelf: \"center\", width: 22, height: 22, borderRadius: 11, alignItems: \"center\", justifyContent: \"center\", overflow: \"hidden\" },\n caption: { position: \"absolute\", left: 12, right: 76, bottom: 16, gap: 6 },\n nameRow: { flexDirection: \"row\", alignItems: \"center\", gap: 6 },\n pill: { paddingHorizontal: 8, paddingVertical: 2, borderRadius: 999 },\n pillText: { fontWeight: \"700\", letterSpacing: 0.4 },\n underline: { textDecorationLine: \"underline\", fontWeight: \"600\" },\n});\n"],"mappings":"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","names":[]}
package/dist/native.d.ts CHANGED
@@ -312,7 +312,7 @@ declare const textStyles: {
312
312
  fontSize: number;
313
313
  lineHeight: number;
314
314
  fontWeight: "700";
315
- fontVariant: "tabular-nums"[];
315
+ fontVariant: ("lining-nums" | "tabular-nums")[];
316
316
  };
317
317
  };
318
318
 
package/dist/native.js CHANGED
@@ -495,7 +495,7 @@ var textStyles = StyleSheet.create({
495
495
  body: { fontSize: 15, lineHeight: 21 },
496
496
  caption: { fontSize: 12, lineHeight: 16 },
497
497
  label: { fontSize: 14, lineHeight: 18, fontWeight: "700" },
498
- mono: { fontSize: 14, lineHeight: 18, fontWeight: "700", fontVariant: ["tabular-nums"] }
498
+ mono: { fontSize: 14, lineHeight: 18, fontWeight: "700", fontVariant: ["lining-nums", "tabular-nums"] }
499
499
  });
500
500
  var styles = textStyles;
501
501
 
@@ -1930,7 +1930,7 @@ function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md"
1930
1930
  var styles13 = StyleSheet13.create({
1931
1931
  root: { flexDirection: "row", alignItems: "baseline", gap: 6 },
1932
1932
  segment: { flexDirection: "row", alignItems: "baseline" },
1933
- value: { fontWeight: "900", fontVariant: ["tabular-nums"], letterSpacing: -0.3 },
1933
+ value: { fontWeight: "900", fontVariant: ["lining-nums", "tabular-nums"], letterSpacing: -0.3 },
1934
1934
  unit: { marginLeft: 2, fontWeight: "700", textTransform: "uppercase" },
1935
1935
  label: { fontWeight: "600", marginRight: 2 }
1936
1936
  });
@@ -2010,7 +2010,7 @@ var styles14 = StyleSheet14.create({
2010
2010
  box: { width: 64, gap: 4 },
2011
2011
  yearBox: { width: 88, gap: 4 },
2012
2012
  part: { fontSize: 11, lineHeight: 14 },
2013
- input: { height: 44, borderWidth: 1, paddingHorizontal: 10, fontSize: 16, fontVariant: ["tabular-nums"], textAlign: "center" },
2013
+ input: { height: 44, borderWidth: 1, paddingHorizontal: 10, fontSize: 16, fontVariant: ["lining-nums", "tabular-nums"], textAlign: "center" },
2014
2014
  caption: { fontSize: 12, lineHeight: 16 },
2015
2015
  disabled: { opacity: 0.5 }
2016
2016
  });
@@ -2155,7 +2155,7 @@ var styles15 = StyleSheet15.create({
2155
2155
  band: { position: "absolute", left: 6, right: 6, borderWidth: StyleSheet15.hairlineWidth },
2156
2156
  column: { minWidth: 56, flexGrow: 1 },
2157
2157
  item: { alignItems: "center", justifyContent: "center", paddingHorizontal: 8 },
2158
- itemText: { fontSize: 18, fontVariant: ["tabular-nums"] },
2158
+ itemText: { fontSize: 18, fontVariant: ["lining-nums", "tabular-nums"] },
2159
2159
  divider: { alignSelf: "center", fontSize: 18, fontWeight: "600" },
2160
2160
  disabled: { opacity: 0.4 }
2161
2161
  });
@@ -2453,7 +2453,7 @@ var styles16 = StyleSheet16.create({
2453
2453
  weekday: { width: 44, textAlign: "center", fontSize: 11, fontWeight: "700", paddingBottom: 4 },
2454
2454
  cell: { width: 44, height: 44, marginVertical: 1 },
2455
2455
  day: { flex: 1, alignItems: "center", justifyContent: "center" },
2456
- dayText: { fontSize: 15, fontVariant: ["tabular-nums"] },
2456
+ dayText: { fontSize: 15, fontVariant: ["lining-nums", "tabular-nums"] },
2457
2457
  node: { width: 5, height: 5, borderRadius: 1, transform: [{ rotate: "45deg" }] },
2458
2458
  todayNode: { position: "absolute", bottom: 5 },
2459
2459
  months: { flexDirection: "row", flexWrap: "wrap", width: 264, gap: 6 },
@@ -2463,11 +2463,11 @@ var styles16 = StyleSheet16.create({
2463
2463
  stripDay: { width: 56, height: 72, alignItems: "center", justifyContent: "center", gap: 2, borderWidth: 1 },
2464
2464
  stripNode: { position: "absolute", top: 6 },
2465
2465
  stripWeekday: { fontSize: 11, fontWeight: "700", letterSpacing: 0.5 },
2466
- stripNumber: { fontSize: 19, fontWeight: "700", fontVariant: ["tabular-nums"] },
2466
+ stripNumber: { fontSize: 19, fontWeight: "700", fontVariant: ["lining-nums", "tabular-nums"] },
2467
2467
  dot: { width: 6, height: 6, borderRadius: 3 },
2468
2468
  slots: { flexDirection: "row", flexWrap: "wrap", gap: 8, alignSelf: "stretch" },
2469
2469
  slot: { minWidth: 88, height: 44, paddingHorizontal: 12, alignItems: "center", justifyContent: "center", borderWidth: 1 },
2470
- slotText: { fontSize: 15, fontWeight: "600", fontVariant: ["tabular-nums"] },
2470
+ slotText: { fontSize: 15, fontWeight: "600", fontVariant: ["lining-nums", "tabular-nums"] },
2471
2471
  field: { gap: 6, alignSelf: "stretch" },
2472
2472
  fieldLabel: { fontSize: 12, lineHeight: 16, fontWeight: "600" },
2473
2473
  caption: { fontSize: 12, lineHeight: 16 },
@@ -4042,7 +4042,7 @@ function NumberTicker({ value, locale, format, trigger = "mount", duration = 110
4042
4042
  };
4043
4043
  }, [value, reduce, trigger, duration, announce, anim, writer]);
4044
4044
  const digits = Number.isInteger(value) ? Math.round(shown) : shown;
4045
- return /* @__PURE__ */ jsx42(Txt, { variant, tone: tone3, "aria-label": writer.format(value), style: [{ fontVariant: ["tabular-nums"] }, style], children: /* @__PURE__ */ jsx42(Text13, { "aria-hidden": true, children: writer.format(digits) }) });
4045
+ return /* @__PURE__ */ jsx42(Txt, { variant, tone: tone3, "aria-label": writer.format(value), style: [{ fontVariant: ["lining-nums", "tabular-nums"] }, style], children: /* @__PURE__ */ jsx42(Text13, { "aria-hidden": true, children: writer.format(digits) }) });
4046
4046
  }
4047
4047
 
4048
4048
  // src/native/onboarding.tsx
@@ -4201,7 +4201,7 @@ function Pagination({ page = 1, pageCount, onPageChange, hasPrevious, hasNext, o
4201
4201
  var styles32 = StyleSheet32.create({
4202
4202
  row: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: 12 },
4203
4203
  button: { width: 44, height: 44, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet32.hairlineWidth },
4204
- status: { fontSize: 13, fontWeight: "600", fontVariant: ["tabular-nums"] }
4204
+ status: { fontSize: 13, fontWeight: "600", fontVariant: ["lining-nums", "tabular-nums"] }
4205
4205
  });
4206
4206
 
4207
4207
  // src/native/permission-prompt.tsx
@@ -5273,7 +5273,7 @@ var styles44 = StyleSheet44.create({
5273
5273
  rootVertical: { alignSelf: "flex-start", alignItems: "center" },
5274
5274
  header: { flexDirection: "row", justifyContent: "space-between", alignItems: "baseline", gap: 12 },
5275
5275
  label: { fontSize: 12, fontWeight: "600" },
5276
- value: { fontSize: 12, fontVariant: ["tabular-nums"] },
5276
+ value: { fontSize: 12, fontVariant: ["lining-nums", "tabular-nums"] },
5277
5277
  control: { height: 44, justifyContent: "center", paddingHorizontal: THUMB / 2 },
5278
5278
  controlVertical: { flex: 1, minHeight: 160, width: 44, alignItems: "center", paddingVertical: THUMB / 2 },
5279
5279
  track: { height: 6 },
@@ -5296,7 +5296,7 @@ var styles44 = StyleSheet44.create({
5296
5296
  },
5297
5297
  bubble: { position: "absolute", bottom: THUMB + 6, left: -17, minWidth: 56, paddingHorizontal: 8, paddingVertical: 4, alignItems: "center" },
5298
5298
  bubbleVertical: { position: "absolute", left: THUMB + 8, top: -2, minWidth: 48, paddingHorizontal: 8, paddingVertical: 4, alignItems: "center" },
5299
- bubbleText: { fontSize: 12, fontWeight: "700", fontVariant: ["tabular-nums"] },
5299
+ bubbleText: { fontSize: 12, fontWeight: "700", fontVariant: ["lining-nums", "tabular-nums"] },
5300
5300
  marks: { height: 16, marginHorizontal: THUMB / 2 },
5301
5301
  mark: { position: "absolute", width: 40, fontSize: 11, fontWeight: "500" },
5302
5302
  disabled: { opacity: 0.4 }