@krizaka/ui 3.3.0 → 3.4.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.
- package/dist/activity-feed.d.ts +199 -0
- package/dist/activity-feed.js +155 -0
- package/dist/activity-feed.js.map +1 -0
- package/dist/argument-card.js +3 -3
- package/dist/chunk-7Z4KHPFC.js +42 -0
- package/dist/chunk-7Z4KHPFC.js.map +1 -0
- package/dist/data-table.js +98 -131
- package/dist/data-table.js.map +1 -1
- package/dist/description-list.d.ts +105 -0
- package/dist/description-list.js +49 -0
- package/dist/description-list.js.map +1 -0
- package/dist/index.js +13 -66
- package/dist/index.js.map +1 -1
- package/dist/kanban.d.ts +132 -0
- package/dist/kanban.js +187 -0
- package/dist/kanban.js.map +1 -0
- package/dist/list.d.ts +153 -0
- package/dist/list.js +130 -0
- package/dist/list.js.map +1 -0
- package/dist/map.d.ts +463 -0
- package/dist/map.js +952 -0
- package/dist/map.js.map +1 -0
- package/dist/motion.css +12 -1
- package/dist/native/map.d.ts +200 -0
- package/dist/native/map.js +673 -0
- package/dist/native/map.js.map +1 -0
- package/dist/native/media-picker.d.ts +58 -0
- package/dist/native/media-picker.js +63 -0
- package/dist/native/media-picker.js.map +1 -0
- package/dist/native.d.ts +568 -6
- package/dist/native.js +1989 -868
- package/dist/native.js.map +1 -1
- package/dist/page-hero.js +3 -3
- package/dist/stat.d.ts +31 -2
- package/dist/stat.js +21 -4
- package/dist/stat.js.map +1 -1
- package/dist/tree-view.d.ts +111 -0
- package/dist/tree-view.js +154 -0
- package/dist/tree-view.js.map +1 -0
- package/package.json +147 -10
- package/registry/achievement.json +1 -1
- package/registry/action-bar.json +1 -1
- package/registry/action-sheet.json +121 -0
- package/registry/activity-feed.json +468 -0
- package/registry/alert.json +1 -1
- package/registry/app-shell.json +1 -1
- package/registry/argument-card.json +1 -1
- package/registry/audio-player.json +1 -1
- package/registry/auth-layout.json +1 -1
- package/registry/avatar.json +58 -3
- package/registry/badge.json +1 -1
- package/registry/button.json +1 -1
- package/registry/card-grid.json +1 -1
- package/registry/card.json +1 -1
- package/registry/catalogue-page.json +1 -1
- package/registry/changelog-page.json +1 -1
- package/registry/checkbox.json +1 -1
- package/registry/chip-link.json +1 -1
- package/registry/chip.json +1 -1
- package/registry/choice-grid.json +1 -1
- package/registry/code-block.json +1 -1
- package/registry/combobox.json +1 -1
- package/registry/command.json +1 -1
- package/registry/component-page.json +1 -1
- package/registry/confirm-button.json +1 -1
- package/registry/contact-page.json +1 -1
- package/registry/continue-prompt.json +1 -1
- package/registry/countdown.json +1 -1
- package/registry/cta-panel.json +1 -1
- package/registry/dashboard-layout.json +1 -1
- package/registry/data-table.json +1 -1
- package/registry/date-picker.json +2 -2
- package/registry/decision-list.json +1 -1
- package/registry/description-list.json +232 -0
- package/registry/detail-layout.json +1 -1
- package/registry/dialog.json +1 -1
- package/registry/docs-article-page.json +1 -1
- package/registry/docs-hub-page.json +1 -1
- package/registry/docs-layout.json +1 -1
- package/registry/dropdown-menu.json +1 -1
- package/registry/empty-state.json +1 -1
- package/registry/error-page.json +1 -1
- package/registry/examples/action-sheet/native/video-actions.d.ts +4 -0
- package/registry/examples/action-sheet/native/video-actions.dark.png +0 -0
- package/registry/examples/action-sheet/native/video-actions.js +30 -0
- package/registry/examples/action-sheet/native/video-actions.light.png +0 -0
- package/registry/examples/action-sheet/native/video-actions.tsx +24 -0
- package/registry/examples/activity-feed/job-activity.d.ts +4 -0
- package/registry/examples/activity-feed/job-activity.js +21 -0
- package/registry/examples/activity-feed/job-activity.tsx +17 -0
- package/registry/examples/activity-feed/live.d.ts +4 -0
- package/registry/examples/activity-feed/live.js +23 -0
- package/registry/examples/activity-feed/live.tsx +24 -0
- package/registry/examples/activity-feed/native/notifications.d.ts +4 -0
- package/registry/examples/activity-feed/native/notifications.dark.png +0 -0
- package/registry/examples/activity-feed/native/notifications.js +18 -0
- package/registry/examples/activity-feed/native/notifications.light.png +0 -0
- package/registry/examples/activity-feed/native/notifications.tsx +18 -0
- package/registry/examples/activity-feed/timeline.d.ts +4 -0
- package/registry/examples/activity-feed/timeline.js +25 -0
- package/registry/examples/activity-feed/timeline.tsx +19 -0
- package/registry/examples/avatar/native/presence.d.ts +4 -0
- package/registry/examples/avatar/native/presence.dark.png +0 -0
- package/registry/examples/avatar/native/presence.js +18 -0
- package/registry/examples/avatar/native/presence.light.png +0 -0
- package/registry/examples/avatar/native/presence.tsx +15 -0
- package/registry/examples/description-list/job-details.d.ts +4 -0
- package/registry/examples/description-list/job-details.js +23 -0
- package/registry/examples/description-list/job-details.tsx +17 -0
- package/registry/examples/description-list/key-value-grid.d.ts +4 -0
- package/registry/examples/description-list/key-value-grid.js +22 -0
- package/registry/examples/description-list/key-value-grid.tsx +16 -0
- package/registry/examples/description-list/native/job-details.d.ts +4 -0
- package/registry/examples/description-list/native/job-details.dark.png +0 -0
- package/registry/examples/description-list/native/job-details.js +33 -0
- package/registry/examples/description-list/native/job-details.light.png +0 -0
- package/registry/examples/description-list/native/job-details.tsx +24 -0
- package/registry/examples/description-list/receipt.d.ts +4 -0
- package/registry/examples/description-list/receipt.js +23 -0
- package/registry/examples/description-list/receipt.tsx +17 -0
- package/registry/examples/fab/native/extended.d.ts +4 -0
- package/registry/examples/fab/native/extended.dark.png +0 -0
- package/registry/examples/fab/native/extended.js +18 -0
- package/registry/examples/fab/native/extended.light.png +0 -0
- package/registry/examples/fab/native/extended.tsx +23 -0
- package/registry/examples/header/native/large-title.d.ts +4 -0
- package/registry/examples/header/native/large-title.dark.png +0 -0
- package/registry/examples/header/native/large-title.js +23 -0
- package/registry/examples/header/native/large-title.light.png +0 -0
- package/registry/examples/header/native/large-title.tsx +31 -0
- package/registry/examples/image-viewer/native/gallery.d.ts +4 -0
- package/registry/examples/image-viewer/native/gallery.dark.png +0 -0
- package/registry/examples/image-viewer/native/gallery.js +22 -0
- package/registry/examples/image-viewer/native/gallery.light.png +0 -0
- package/registry/examples/image-viewer/native/gallery.tsx +21 -0
- package/registry/examples/kanban/moderation.d.ts +4 -0
- package/registry/examples/kanban/moderation.js +35 -0
- package/registry/examples/kanban/moderation.tsx +37 -0
- package/registry/examples/list/jobs.d.ts +4 -0
- package/registry/examples/list/jobs.js +35 -0
- package/registry/examples/list/jobs.tsx +33 -0
- package/registry/examples/list/selectable.d.ts +4 -0
- package/registry/examples/list/selectable.js +33 -0
- package/registry/examples/list/selectable.tsx +30 -0
- package/registry/examples/list/virtualized.d.ts +4 -0
- package/registry/examples/list/virtualized.js +22 -0
- package/registry/examples/list/virtualized.tsx +17 -0
- package/registry/examples/loader/native/block.d.ts +4 -0
- package/registry/examples/loader/native/block.dark.png +0 -0
- package/registry/examples/loader/native/block.js +12 -0
- package/registry/examples/loader/native/block.light.png +0 -0
- package/registry/examples/loader/native/block.tsx +11 -0
- package/registry/examples/loader/native/job-wait.d.ts +4 -0
- package/registry/examples/loader/native/job-wait.dark.png +0 -0
- package/registry/examples/loader/native/job-wait.js +17 -0
- package/registry/examples/loader/native/job-wait.light.png +0 -0
- package/registry/examples/loader/native/job-wait.tsx +14 -0
- package/registry/examples/map/cluster.d.ts +4 -0
- package/registry/examples/map/cluster.js +16 -0
- package/registry/examples/map/cluster.tsx +18 -0
- package/registry/examples/map/location-picker.d.ts +4 -0
- package/registry/examples/map/location-picker.js +24 -0
- package/registry/examples/map/location-picker.tsx +22 -0
- package/registry/examples/map/native/location-picker.d.ts +4 -0
- package/registry/examples/map/native/location-picker.dark.png +0 -0
- package/registry/examples/map/native/location-picker.js +14 -0
- package/registry/examples/map/native/location-picker.light.png +0 -0
- package/registry/examples/map/native/location-picker.tsx +13 -0
- package/registry/examples/map/native/places.d.ts +4 -0
- package/registry/examples/map/native/places.dark.png +0 -0
- package/registry/examples/map/native/places.js +25 -0
- package/registry/examples/map/native/places.light.png +0 -0
- package/registry/examples/map/native/places.tsx +27 -0
- package/registry/examples/map/places.d.ts +4 -0
- package/registry/examples/map/places.js +28 -0
- package/registry/examples/map/places.tsx +28 -0
- package/registry/examples/map/static.d.ts +4 -0
- package/registry/examples/map/static.js +22 -0
- package/registry/examples/map/static.tsx +18 -0
- package/registry/examples/media-picker/native/story.d.ts +4 -0
- package/registry/examples/media-picker/native/story.dark.png +0 -0
- package/registry/examples/media-picker/native/story.js +30 -0
- package/registry/examples/media-picker/native/story.light.png +0 -0
- package/registry/examples/media-picker/native/story.tsx +26 -0
- package/registry/examples/meter/native/credits.d.ts +4 -0
- package/registry/examples/meter/native/credits.dark.png +0 -0
- package/registry/examples/meter/native/credits.js +15 -0
- package/registry/examples/meter/native/credits.light.png +0 -0
- package/registry/examples/meter/native/credits.tsx +12 -0
- package/registry/examples/meter/native/split-ring.d.ts +4 -0
- package/registry/examples/meter/native/split-ring.dark.png +0 -0
- package/registry/examples/meter/native/split-ring.js +24 -0
- package/registry/examples/meter/native/split-ring.light.png +0 -0
- package/registry/examples/meter/native/split-ring.tsx +19 -0
- package/registry/examples/number-ticker/native/balance.d.ts +4 -0
- package/registry/examples/number-ticker/native/balance.dark.png +0 -0
- package/registry/examples/number-ticker/native/balance.js +18 -0
- package/registry/examples/number-ticker/native/balance.light.png +0 -0
- package/registry/examples/number-ticker/native/balance.tsx +17 -0
- package/registry/examples/onboarding/native/first-launch.d.ts +4 -0
- package/registry/examples/onboarding/native/first-launch.dark.png +0 -0
- package/registry/examples/onboarding/native/first-launch.js +23 -0
- package/registry/examples/onboarding/native/first-launch.light.png +0 -0
- package/registry/examples/onboarding/native/first-launch.tsx +19 -0
- package/registry/examples/otp-input/native/invalid.d.ts +4 -0
- package/registry/examples/otp-input/native/invalid.dark.png +0 -0
- package/registry/examples/otp-input/native/invalid.js +15 -0
- package/registry/examples/otp-input/native/invalid.light.png +0 -0
- package/registry/examples/otp-input/native/invalid.tsx +14 -0
- package/registry/examples/otp-input/native/verify.d.ts +4 -0
- package/registry/examples/otp-input/native/verify.dark.png +0 -0
- package/registry/examples/otp-input/native/verify.js +17 -0
- package/registry/examples/otp-input/native/verify.light.png +0 -0
- package/registry/examples/otp-input/native/verify.tsx +14 -0
- package/registry/examples/permission-prompt/native/blocked.d.ts +4 -0
- package/registry/examples/permission-prompt/native/blocked.dark.png +0 -0
- package/registry/examples/permission-prompt/native/blocked.js +25 -0
- package/registry/examples/permission-prompt/native/blocked.light.png +0 -0
- package/registry/examples/permission-prompt/native/blocked.tsx +21 -0
- package/registry/examples/permission-prompt/native/camera.d.ts +4 -0
- package/registry/examples/permission-prompt/native/camera.dark.png +0 -0
- package/registry/examples/permission-prompt/native/camera.js +25 -0
- package/registry/examples/permission-prompt/native/camera.light.png +0 -0
- package/registry/examples/permission-prompt/native/camera.tsx +21 -0
- package/registry/examples/pull-to-refresh/native/feed.d.ts +4 -0
- package/registry/examples/pull-to-refresh/native/feed.dark.png +0 -0
- package/registry/examples/pull-to-refresh/native/feed.js +14 -0
- package/registry/examples/pull-to-refresh/native/feed.light.png +0 -0
- package/registry/examples/pull-to-refresh/native/feed.tsx +19 -0
- package/registry/examples/search-field/native/cancel.d.ts +4 -0
- package/registry/examples/search-field/native/cancel.dark.png +0 -0
- package/registry/examples/search-field/native/cancel.js +14 -0
- package/registry/examples/search-field/native/cancel.light.png +0 -0
- package/registry/examples/search-field/native/cancel.tsx +13 -0
- package/registry/examples/stat/grid.d.ts +4 -0
- package/registry/examples/stat/grid.js +17 -0
- package/registry/examples/stat/grid.tsx +14 -0
- package/registry/examples/stepper/native/run.d.ts +4 -0
- package/registry/examples/stepper/native/run.dark.png +0 -0
- package/registry/examples/stepper/native/run.js +24 -0
- package/registry/examples/stepper/native/run.light.png +0 -0
- package/registry/examples/stepper/native/run.tsx +20 -0
- package/registry/examples/swipeable-row/native/conversation.d.ts +4 -0
- package/registry/examples/swipeable-row/native/conversation.dark.png +0 -0
- package/registry/examples/swipeable-row/native/conversation.js +30 -0
- package/registry/examples/swipeable-row/native/conversation.light.png +0 -0
- package/registry/examples/swipeable-row/native/conversation.tsx +27 -0
- package/registry/examples/tab-bar/native/main-sections.d.ts +4 -0
- package/registry/examples/tab-bar/native/main-sections.dark.png +0 -0
- package/registry/examples/tab-bar/native/main-sections.js +29 -0
- package/registry/examples/tab-bar/native/main-sections.light.png +0 -0
- package/registry/examples/tab-bar/native/main-sections.tsx +30 -0
- package/registry/examples/tabs/native/sections.d.ts +4 -0
- package/registry/examples/tabs/native/sections.dark.png +0 -0
- package/registry/examples/tabs/native/sections.js +23 -0
- package/registry/examples/tabs/native/sections.light.png +0 -0
- package/registry/examples/tabs/native/sections.tsx +19 -0
- package/registry/examples/tabs/native/segmented.d.ts +4 -0
- package/registry/examples/tabs/native/segmented.dark.png +0 -0
- package/registry/examples/tabs/native/segmented.js +22 -0
- package/registry/examples/tabs/native/segmented.light.png +0 -0
- package/registry/examples/tabs/native/segmented.tsx +18 -0
- package/registry/examples/toast/native/snackbar.d.ts +4 -0
- package/registry/examples/toast/native/snackbar.dark.png +0 -0
- package/registry/examples/toast/native/snackbar.js +23 -0
- package/registry/examples/toast/native/snackbar.light.png +0 -0
- package/registry/examples/toast/native/snackbar.tsx +21 -0
- package/registry/examples/tree-view/docs.d.ts +4 -0
- package/registry/examples/tree-view/docs.js +24 -0
- package/registry/examples/tree-view/docs.tsx +22 -0
- package/registry/examples/tree-view/lazy.d.ts +4 -0
- package/registry/examples/tree-view/lazy.js +21 -0
- package/registry/examples/tree-view/lazy.tsx +19 -0
- package/registry/fab.json +122 -0
- package/registry/field.json +1 -1
- package/registry/file-upload.json +2 -2
- package/registry/filter-bar.json +1 -1
- package/registry/form.json +2 -2
- package/registry/gallery-page.json +1 -1
- package/registry/glow-card.json +1 -1
- package/registry/goal-gauge.json +1 -1
- package/registry/header.json +137 -0
- package/registry/how-it-works-page.json +1 -1
- package/registry/image-cropper.json +1 -1
- package/registry/image-viewer.json +107 -0
- package/registry/index.json +299 -25
- package/registry/iso.json +1 -1
- package/registry/kanban.json +253 -0
- package/registry/kbd.json +1 -1
- package/registry/landing-page.json +1 -1
- package/registry/landscape.json +1 -1
- package/registry/legal-page.json +1 -1
- package/registry/link-card.json +1 -1
- package/registry/list.json +367 -30
- package/registry/loader.json +157 -4
- package/registry/longform-page.json +1 -1
- package/registry/map.json +1368 -0
- package/registry/marketing-layout.json +1 -1
- package/registry/marquee.json +1 -1
- package/registry/mascot-quote.json +1 -1
- package/registry/mascot-state.json +1 -1
- package/registry/mascots.json +1 -1
- package/registry/media-capture.json +1 -1
- package/registry/media-picker.json +129 -0
- package/registry/meter.json +136 -4
- package/registry/nav-bar.json +1 -1
- package/registry/number-ticker.json +96 -4
- package/registry/onboarding.json +95 -0
- package/registry/otp-input.json +150 -0
- package/registry/page-header.json +1 -1
- package/registry/page-hero.json +1 -1
- package/registry/page.json +1 -1
- package/registry/pagination.json +1 -1
- package/registry/permission-prompt.json +172 -0
- package/registry/pointer-light.json +1 -1
- package/registry/popover.json +1 -1
- package/registry/pricing-page.json +1 -1
- package/registry/product-page.json +1 -1
- package/registry/profile-card.json +1 -1
- package/registry/progress.json +2 -2
- package/registry/promise-card.json +1 -1
- package/registry/pull-to-refresh.json +74 -0
- package/registry/radio-group.json +1 -1
- package/registry/scroll-stage.json +1 -1
- package/registry/search-field.json +30 -3
- package/registry/section-backdrop.json +1 -1
- package/registry/separator.json +1 -1
- package/registry/settings-layout.json +1 -1
- package/registry/skeleton.json +1 -1
- package/registry/slider.json +1 -1
- package/registry/slot.json +1 -1
- package/registry/spinner.json +1 -1
- package/registry/split-view.json +1 -1
- package/registry/stage-banner.json +1 -1
- package/registry/stat.json +68 -5
- package/registry/status-page.json +1 -1
- package/registry/stepper.json +75 -4
- package/registry/swipeable-row.json +124 -0
- package/registry/switch.json +1 -1
- package/registry/tab-bar.json +115 -0
- package/registry/tabs.json +94 -4
- package/registry/tag-input.json +1 -1
- package/registry/terminal-replay.json +1 -1
- package/registry/theme.json +8 -1
- package/registry/toast.json +17 -3
- package/registry/toc.json +1 -1
- package/registry/tooltip.json +1 -1
- package/registry/tree-view.json +291 -0
- package/registry/video-player.json +1 -1
- package/registry/video-trimmer.json +1 -1
- package/registry/virtual.json +1 -1
- package/skills/map/SKILL.md +35 -0
package/registry/toast.json
CHANGED
|
@@ -136,7 +136,9 @@
|
|
|
136
136
|
"differences": [
|
|
137
137
|
"`Toaster` takes `offset` (the safe-area inset) instead of a position; mount it inside `ThemeProvider`.",
|
|
138
138
|
"Actions take `onPress`; a toast takes `onPress` to open what it is about.",
|
|
139
|
-
"No `toast.custom`: an `icon` before the text instead."
|
|
139
|
+
"No `toast.custom`: an `icon` before the text instead.",
|
|
140
|
+
"A sideways swipe dismisses a toast; its tone plays a haptic when the app gives `haptics`.",
|
|
141
|
+
"A snackbar is `Toaster position=\"bottom\"` with one `action`."
|
|
140
142
|
],
|
|
141
143
|
"props": [
|
|
142
144
|
{
|
|
@@ -205,13 +207,25 @@
|
|
|
205
207
|
"dark": "examples/toast/native/notification.dark.png",
|
|
206
208
|
"light": "examples/toast/native/notification.light.png"
|
|
207
209
|
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"name": "snackbar",
|
|
213
|
+
"title": "Snackbar",
|
|
214
|
+
"description": "At the bottom, one action, swiped away.",
|
|
215
|
+
"path": "examples/toast/native/snackbar.tsx",
|
|
216
|
+
"module": "@krizaka/ui/registry/examples/toast/native/snackbar",
|
|
217
|
+
"code": "import { Button, toast, Toaster } from \"@krizaka/ui/native\";\nimport { useEffect } from \"react\";\nimport { View } from \"react-native\";\n\nconst archive = () => toast(\"Conversation archived\", { id: \"archived\", action: { label: \"Undo\", onPress: () => undefined } });\n\n// A snackbar: at the bottom, above the tab bar (`offset`), one action; swipe it away, a tick for its tone.\nexport default function NativeToastSnackbar({ defaultOpen = false }: { defaultOpen?: boolean }) {\n useEffect(() => {\n if (!defaultOpen) return;\n toast.dismiss();\n archive();\n return () => toast.dismiss();\n }, [defaultOpen]);\n return (\n <View style={{ width: 360, height: 200 }}>\n <Button variant=\"outline\" label=\"Archive\" onPress={archive} />\n <Toaster closeLabel=\"Dismiss\" position=\"bottom\" offset={16} duration={defaultOpen ? Number.POSITIVE_INFINITY : 5000} />\n </View>\n );\n}\n",
|
|
218
|
+
"screenshots": {
|
|
219
|
+
"dark": "examples/toast/native/snackbar.dark.png",
|
|
220
|
+
"light": "examples/toast/native/snackbar.light.png"
|
|
221
|
+
}
|
|
208
222
|
}
|
|
209
223
|
]
|
|
210
224
|
},
|
|
211
225
|
"files": [
|
|
212
226
|
{
|
|
213
227
|
"path": "meta.ts",
|
|
214
|
-
"content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"iso\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"switch\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
|
|
228
|
+
"content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"activity-feed\"\n | \"action-sheet\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"description-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"fab\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"header\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"image-viewer\"\n | \"iso\"\n | \"kanban\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"map\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"media-picker\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"onboarding\"\n | \"otp-input\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"permission-prompt\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"pull-to-refresh\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"swipeable-row\"\n | \"switch\"\n | \"tab-bar\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"tree-view\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
|
|
215
229
|
},
|
|
216
230
|
{
|
|
217
231
|
"path": "toast/index.ts",
|
|
@@ -219,7 +233,7 @@
|
|
|
219
233
|
},
|
|
220
234
|
{
|
|
221
235
|
"path": "toast/meta.ts",
|
|
222
|
-
"content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Toast\",\n summary:\n \"A short message that comes and goes — with the time it has left drawn and paused under the pointer, an undo that waits before an action is final, a long task updated in place, and repeats folded into one toast that counts.\",\n status: \"stable\",\n category: \"feedback\",\n platforms: \"both\",\n whenToUse: [\n \"To confirm the result of an action: saved, sent, payment received.\",\n \"For an event the user did not trigger but should know: a new follower, a live auction.\",\n \"With an action (“Retry”, “Undo”) when there is one obvious next step.\",\n ],\n whenNotToUse: [\n { when: \"For a message that must stay until the situation changes.\", use: \"alert\" },\n { when: \"When the user must answer.\", use: \"dialog\" },\n { when: \"To report a form's errors: show them next to the fields.\", use: \"field\" },\n ],\n bestPractices: [\n \"Mount one `Toaster` in the root layout, with its `label` and `closeLabel` translated.\",\n \"A title in a few words, a description only if it adds something.\",\n \"Never put the only way to do something in a toast: it goes away.\",\n \"For what can be undone, act now and commit later: `undoToast` with `onUndo` and `onCommit` — no confirmation dialog.\",\n \"A background task: one `progressToast` updated with the same `id`, never a new toast per step.\",\n \"Events that repeat (messages, retries): `groupedToast` with a `countLabel` — one toast that counts, not a pile.\",\n ],\n accessibility: {\n keyboard: [\n { keys: \"F8\", action: \"Moves the focus to the toasts region (sonner's hotkey).\" },\n { keys: \"Tab / Enter\", action: \"Reach and press a toast's action or close button.\" },\n ],\n notes: [\"The region is a landmark named by `label`; toasts are announced politely.\", \"Toasts pause while hovered or focused.\"],\n },\n related: [\"alert\", \"dialog\", \"confirm-button\"],\n web: {\n imports: [\"toast\", \"Toaster\", \"undoToast\", \"progressToast\", \"groupedToast\"],\n examples: [\n { name: \"undo\", title: \"Undo before it is final\", description: \"`undoToast`: archived now, final when the hairline runs out — paused while you hover it.\" },\n { name: \"upload-progress\", title: \"A task in the background\", description: \"`progressToast`: one toast updated in place, the glyph and a bar growing, a success at 100 %.\" },\n { name: \"grouped\", title: \"Repeats fold\", description: \"`groupedToast`: five messages become one toast that counts “5 new messages”.\" },\n { name: \"tones\", title: \"Tones\", description: \"Default, success, warning and error with an action.\" },\n { name: \"custom\", title: \"Custom\", description: \"`toast.custom`: your JSX in the platform's shell.\" },\n ],\n },\n native: {\n imports: [\"toast\", \"Toaster\"],\n differences: [\n \"`Toaster` takes `offset` (the safe-area inset) instead of a position; mount it inside `ThemeProvider`.\",\n \"Actions take `onPress`; a toast takes `onPress` to open what it is about.\",\n \"No `toast.custom`: an `icon` before the text instead.\",\n ],\n examples: [\n { name: \"tones\", title: \"Tones\", description: \"Default, success, and error with an action.\" },\n { name: \"notification\", title: \"Notification\", description: \"An icon, tap to open it; `id` shows it once.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
|
|
236
|
+
"content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Toast\",\n summary:\n \"A short message that comes and goes — with the time it has left drawn and paused under the pointer, an undo that waits before an action is final, a long task updated in place, and repeats folded into one toast that counts.\",\n status: \"stable\",\n category: \"feedback\",\n platforms: \"both\",\n whenToUse: [\n \"To confirm the result of an action: saved, sent, payment received.\",\n \"For an event the user did not trigger but should know: a new follower, a live auction.\",\n \"With an action (“Retry”, “Undo”) when there is one obvious next step.\",\n ],\n whenNotToUse: [\n { when: \"For a message that must stay until the situation changes.\", use: \"alert\" },\n { when: \"When the user must answer.\", use: \"dialog\" },\n { when: \"To report a form's errors: show them next to the fields.\", use: \"field\" },\n ],\n bestPractices: [\n \"Mount one `Toaster` in the root layout, with its `label` and `closeLabel` translated.\",\n \"A title in a few words, a description only if it adds something.\",\n \"Never put the only way to do something in a toast: it goes away.\",\n \"For what can be undone, act now and commit later: `undoToast` with `onUndo` and `onCommit` — no confirmation dialog.\",\n \"A background task: one `progressToast` updated with the same `id`, never a new toast per step.\",\n \"Events that repeat (messages, retries): `groupedToast` with a `countLabel` — one toast that counts, not a pile.\",\n ],\n accessibility: {\n keyboard: [\n { keys: \"F8\", action: \"Moves the focus to the toasts region (sonner's hotkey).\" },\n { keys: \"Tab / Enter\", action: \"Reach and press a toast's action or close button.\" },\n ],\n notes: [\"The region is a landmark named by `label`; toasts are announced politely.\", \"Toasts pause while hovered or focused.\"],\n },\n related: [\"alert\", \"dialog\", \"confirm-button\"],\n web: {\n imports: [\"toast\", \"Toaster\", \"undoToast\", \"progressToast\", \"groupedToast\"],\n examples: [\n { name: \"undo\", title: \"Undo before it is final\", description: \"`undoToast`: archived now, final when the hairline runs out — paused while you hover it.\" },\n { name: \"upload-progress\", title: \"A task in the background\", description: \"`progressToast`: one toast updated in place, the glyph and a bar growing, a success at 100 %.\" },\n { name: \"grouped\", title: \"Repeats fold\", description: \"`groupedToast`: five messages become one toast that counts “5 new messages”.\" },\n { name: \"tones\", title: \"Tones\", description: \"Default, success, warning and error with an action.\" },\n { name: \"custom\", title: \"Custom\", description: \"`toast.custom`: your JSX in the platform's shell.\" },\n ],\n },\n native: {\n imports: [\"toast\", \"Toaster\"],\n differences: [\n \"`Toaster` takes `offset` (the safe-area inset) instead of a position; mount it inside `ThemeProvider`.\",\n \"Actions take `onPress`; a toast takes `onPress` to open what it is about.\",\n \"No `toast.custom`: an `icon` before the text instead.\",\n \"A sideways swipe dismisses a toast; its tone plays a haptic when the app gives `haptics`.\",\n \"A snackbar is `Toaster position=\\\"bottom\\\"` with one `action`.\",\n ],\n examples: [\n { name: \"tones\", title: \"Tones\", description: \"Default, success, and error with an action.\" },\n { name: \"notification\", title: \"Notification\", description: \"An icon, tap to open it; `id` shows it once.\" },\n { name: \"snackbar\", title: \"Snackbar\", description: \"At the bottom, one action, swiped away.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
|
|
223
237
|
},
|
|
224
238
|
{
|
|
225
239
|
"path": "toast/toast.tsx",
|
package/registry/toc.json
CHANGED
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"files": [
|
|
97
97
|
{
|
|
98
98
|
"path": "meta.ts",
|
|
99
|
-
"content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"iso\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"switch\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
|
|
99
|
+
"content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"activity-feed\"\n | \"action-sheet\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"description-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"fab\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"header\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"image-viewer\"\n | \"iso\"\n | \"kanban\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"map\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"media-picker\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"onboarding\"\n | \"otp-input\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"permission-prompt\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"pull-to-refresh\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"swipeable-row\"\n | \"switch\"\n | \"tab-bar\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"tree-view\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
|
|
100
100
|
},
|
|
101
101
|
{
|
|
102
102
|
"path": "toc/index.ts",
|
package/registry/tooltip.json
CHANGED
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
},
|
|
142
142
|
{
|
|
143
143
|
"path": "meta.ts",
|
|
144
|
-
"content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"iso\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"switch\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
|
|
144
|
+
"content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"activity-feed\"\n | \"action-sheet\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"description-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"fab\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"header\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"image-viewer\"\n | \"iso\"\n | \"kanban\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"map\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"media-picker\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"onboarding\"\n | \"otp-input\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"permission-prompt\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"pull-to-refresh\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"swipeable-row\"\n | \"switch\"\n | \"tab-bar\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"tree-view\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
|
|
145
145
|
},
|
|
146
146
|
{
|
|
147
147
|
"path": "tooltip/index.ts",
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tree-view",
|
|
3
|
+
"type": "primitive",
|
|
4
|
+
"title": "Tree view",
|
|
5
|
+
"summary": "A hierarchy the keyboard walks — the ARIA tree: one tab stop, the arrows move and open, a letter jumps, branches load on demand.",
|
|
6
|
+
"description": "A hierarchy the keyboard walks — the ARIA tree: one tab stop, the arrows move and open, a letter jumps, branches load on demand.",
|
|
7
|
+
"status": "beta",
|
|
8
|
+
"category": "navigation",
|
|
9
|
+
"platforms": "web",
|
|
10
|
+
"whenToUse": [
|
|
11
|
+
"The documentation's sections (krizaka.com/docs).",
|
|
12
|
+
"A studio's datasets, folders of files."
|
|
13
|
+
],
|
|
14
|
+
"whenNotToUse": [
|
|
15
|
+
{
|
|
16
|
+
"when": "For two levels or fewer: a list with headings reads better.",
|
|
17
|
+
"use": "list"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"when": "On a phone: drill down screen by screen with a list.",
|
|
21
|
+
"use": "list"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"bestPractices": [
|
|
25
|
+
"Open the branch of the selected node at first (`defaultExpanded`).",
|
|
26
|
+
"Load big branches on demand (`hasChildren` + `onLoadChildren`)."
|
|
27
|
+
],
|
|
28
|
+
"accessibility": {
|
|
29
|
+
"keyboard": [
|
|
30
|
+
{
|
|
31
|
+
"keys": "Arrow Down / Arrow Up",
|
|
32
|
+
"action": "Move to the next or previous visible node."
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"keys": "Arrow Right",
|
|
36
|
+
"action": "Opens a closed branch, or moves to its first child."
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"keys": "Arrow Left",
|
|
40
|
+
"action": "Closes an open branch, or moves to its parent."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"keys": "Home / End",
|
|
44
|
+
"action": "Move to the first or last visible node."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"keys": "Enter / Space",
|
|
48
|
+
"action": "Select the node (`onSelect`)."
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"keys": "A letter",
|
|
52
|
+
"action": "Moves to the next node whose name starts with it."
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"notes": [
|
|
56
|
+
"`tree`, `treeitem` and `group` with level, position and size; a loading branch is busy.",
|
|
57
|
+
"Web only: a phone drills down with lists."
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"related": [
|
|
61
|
+
"list",
|
|
62
|
+
"nav-bar"
|
|
63
|
+
],
|
|
64
|
+
"web": {
|
|
65
|
+
"entry": "@krizaka/ui/tree-view",
|
|
66
|
+
"import": "import { TreeView } from \"@krizaka/ui/tree-view\";",
|
|
67
|
+
"props": [
|
|
68
|
+
{
|
|
69
|
+
"component": "TreeView",
|
|
70
|
+
"description": "A hierarchy to browse — documentation sections, a studio's datasets, folders: one tab stop, the arrows walk it (→\nopens, ← closes or goes up), Home/End, a letter jumps to the next name; branches can load their children on demand.",
|
|
71
|
+
"props": [
|
|
72
|
+
{
|
|
73
|
+
"name": "aria-label",
|
|
74
|
+
"type": "string",
|
|
75
|
+
"default": null,
|
|
76
|
+
"description": "The tree's accessible name (“Documentation”).",
|
|
77
|
+
"required": true
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "nodes",
|
|
81
|
+
"type": "readonly TreeNode[]",
|
|
82
|
+
"default": null,
|
|
83
|
+
"description": "The roots.",
|
|
84
|
+
"required": true
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "className",
|
|
88
|
+
"type": "string",
|
|
89
|
+
"default": null,
|
|
90
|
+
"description": "Classes merged on the tree.",
|
|
91
|
+
"required": false
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "defaultExpanded",
|
|
95
|
+
"type": "readonly string[]",
|
|
96
|
+
"default": "[]",
|
|
97
|
+
"description": "The ids open at first, uncontrolled.",
|
|
98
|
+
"required": false
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "defaultSelected",
|
|
102
|
+
"type": "string | null",
|
|
103
|
+
"default": "null",
|
|
104
|
+
"description": "The selected node at first, uncontrolled.",
|
|
105
|
+
"required": false
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "expanded",
|
|
109
|
+
"type": "readonly string[]",
|
|
110
|
+
"default": null,
|
|
111
|
+
"description": "The ids of the open branches (controlled).",
|
|
112
|
+
"required": false
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"name": "loadingLabel",
|
|
116
|
+
"type": "string",
|
|
117
|
+
"default": "Loading",
|
|
118
|
+
"description": "The words of a branch that is loading (“Loading”).",
|
|
119
|
+
"required": false
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "onExpandedChange",
|
|
123
|
+
"type": "((expanded: string[]) => void)",
|
|
124
|
+
"default": null,
|
|
125
|
+
"description": "Called with the open branches.",
|
|
126
|
+
"required": false
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "onLoadChildren",
|
|
130
|
+
"type": "((node: TreeNode) => void)",
|
|
131
|
+
"default": null,
|
|
132
|
+
"description": "Called when a branch with `hasChildren` and no `children` opens: fetch them, then pass them in `nodes`.",
|
|
133
|
+
"required": false
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "onSelect",
|
|
137
|
+
"type": "((node: TreeNode) => void)",
|
|
138
|
+
"default": null,
|
|
139
|
+
"description": "Called when a node is chosen (click, Enter or Space): navigate, open the file.",
|
|
140
|
+
"required": false
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"name": "selected",
|
|
144
|
+
"type": "string | null",
|
|
145
|
+
"default": null,
|
|
146
|
+
"description": "The selected node (controlled).",
|
|
147
|
+
"required": false
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"examples": [
|
|
153
|
+
{
|
|
154
|
+
"name": "docs",
|
|
155
|
+
"title": "Documentation",
|
|
156
|
+
"description": "Products, sections and pages, the current page selected.",
|
|
157
|
+
"path": "examples/tree-view/docs.tsx",
|
|
158
|
+
"module": "@krizaka/ui/registry/examples/tree-view/docs",
|
|
159
|
+
"code": "\"use client\";\n\nimport { TreeView } from \"@krizaka/ui/tree-view\";\n\nconst nodes = [\n {\n id: \"orazaka\",\n label: \"Orazaka\",\n children: [\n { id: \"getting-started\", label: \"Getting started\" },\n { id: \"studios\", label: \"Studios\", meta: \"12\", children: [{ id: \"dubbing\", label: \"Dubbing\" }, { id: \"transcript\", label: \"Transcript\" }, { id: \"clips\", label: \"Clips\" }] },\n { id: \"api\", label: \"API reference\" },\n ],\n },\n { id: \"orochia\", label: \"Orochia\", children: [{ id: \"auctions\", label: \"Auctions\" }, { id: \"challenges\", label: \"Challenges\" }] },\n { id: \"ui\", label: \"Krizaka UI\", children: [{ id: \"components\", label: \"Components\" }] },\n];\n\n// The documentation's sections: one tab stop, the arrows walk and open, a letter jumps.\nexport default function TreeViewDocs() {\n return <TreeView aria-label=\"Documentation\" nodes={nodes} defaultExpanded={[\"orazaka\", \"studios\"]} defaultSelected=\"dubbing\" className=\"max-w-xs\" />;\n}\n"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"name": "lazy",
|
|
163
|
+
"title": "Loaded on demand",
|
|
164
|
+
"description": "A branch fetches its files when it opens.",
|
|
165
|
+
"path": "examples/tree-view/lazy.tsx",
|
|
166
|
+
"module": "@krizaka/ui/registry/examples/tree-view/lazy",
|
|
167
|
+
"code": "\"use client\";\n\nimport { type TreeNode, TreeView } from \"@krizaka/ui/tree-view\";\nimport { useState } from \"react\";\n\n// A studio's datasets: a branch loads its files when it opens (here after 600 ms).\nexport default function TreeViewLazy() {\n const [nodes, setNodes] = useState<TreeNode[]>([\n { id: \"voices\", label: \"Voices\", hasChildren: true, meta: \"3\" },\n { id: \"glossaries\", label: \"Glossaries\", hasChildren: true, meta: \"2\" },\n { id: \"readme\", label: \"README.md\" },\n ]);\n const load = (node: TreeNode) =>\n setTimeout(() => {\n const files = Array.from({ length: Number(node.meta) }, (_, i) => ({ id: `${node.id}-${i}`, label: `${node.label.toLowerCase()}-${i + 1}.json` }));\n setNodes((all) => all.map((n) => (n.id === node.id ? { ...n, children: files } : n)));\n }, 600);\n return <TreeView aria-label=\"Datasets\" nodes={nodes} onLoadChildren={load} loadingLabel=\"Loading the files\" className=\"max-w-xs\" />;\n}\n"
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
},
|
|
171
|
+
"native": null,
|
|
172
|
+
"files": [
|
|
173
|
+
{
|
|
174
|
+
"path": "glyphs.tsx",
|
|
175
|
+
"content": "// The small line glyphs the data and media primitives draw (play, volume, search, chevrons…): decorative, 24-unit\n// box, `currentColor`, sized by the caller's class. Shared by the entries that need them; never exported on its own —\n// a product draws its own icons with @krizaka/icons.\nimport type * as React from \"react\";\n\ntype GlyphProps = { className?: string };\n\nfunction Glyph({ className = \"h-4 w-4\", fill, children }: GlyphProps & { fill?: boolean; children: React.ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n className={className}\n fill={fill ? \"currentColor\" : \"none\"}\n stroke={fill ? \"none\" : \"currentColor\"}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n focusable=\"false\"\n >\n {children}\n </svg>\n );\n}\n\nexport const PlayGlyph = (p: GlyphProps) => (\n <Glyph {...p} fill>\n <path d=\"M8 5.5v13a1 1 0 0 0 1.5.86l10.4-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5Z\" />\n </Glyph>\n);\nexport const PauseGlyph = (p: GlyphProps) => (\n <Glyph {...p} fill>\n <rect x=\"6\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n <rect x=\"14\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n </Glyph>\n);\nexport const VolumeGlyph = ({ muted, ...p }: GlyphProps & { muted?: boolean }) => (\n <Glyph {...p}>\n <path d=\"M11 5 6 9H3v6h3l5 4V5Z\" />\n {muted ? <path d=\"m22 9-6 6m0-6 6 6\" /> : <path d=\"M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13\" />}\n </Glyph>\n);\nexport const FullscreenGlyph = ({ exit, ...p }: GlyphProps & { exit?: boolean }) => (\n <Glyph {...p}>\n {exit ? <path d=\"M9 4v5H4m11-5v5h5M9 20v-5H4m11 5v-5h5\" /> : <path d=\"M4 9V4h5m6 0h5v5M4 15v5h5m11-5v5h-5\" />}\n </Glyph>\n);\nexport const CaptionsGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" />\n <path d=\"M10 10.5a2 2 0 1 0 0 3M17 10.5a2 2 0 1 0 0 3\" />\n </Glyph>\n);\nexport const PipGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" />\n <rect x=\"12\" y=\"12\" width=\"6\" height=\"4\" rx=\"1\" />\n </Glyph>\n);\nexport const SearchGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n </Glyph>\n);\nexport const CloseGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </Glyph>\n);\nexport const ChevronGlyph = ({ direction = \"down\", ...p }: GlyphProps & { direction?: \"left\" | \"right\" | \"up\" | \"down\" }) => (\n <Glyph {...p}>\n <path d={{ left: \"m15 6-6 6 6 6\", right: \"m9 6 6 6-6 6\", up: \"m6 15 6-6 6 6\", down: \"m6 9 6 6 6-6\" }[direction]} />\n </Glyph>\n);\nexport const CheckGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M20 6 9 17l-5-5\" />\n </Glyph>\n);\nexport const PlusGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M12 5v14M5 12h14\" />\n </Glyph>\n);\nexport const CalendarGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\" />\n <path d=\"M3 10h18M8 3v4M16 3v4\" />\n </Glyph>\n);\nexport const UploadGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M12 16V4m0 0L7 9m5-5 5 5\" />\n <path d=\"M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\" />\n </Glyph>\n);\nexport const FileGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8l-5-5Z\" />\n <path d=\"M14 3v5h5\" />\n </Glyph>\n);\nexport const CameraGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M4 8h3l2-3h6l2 3h3a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1Z\" />\n <circle cx=\"12\" cy=\"13.5\" r=\"3.5\" />\n </Glyph>\n);\nexport const FlipGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M4 12a8 8 0 0 1 14-5.3M20 12a8 8 0 0 1-14 5.3\" />\n <path d=\"M18 3v4h-4M6 21v-4h4\" />\n </Glyph>\n);\nexport const RetryGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M4 12a8 8 0 1 0 2.3-5.7L4 8.5\" />\n <path d=\"M4 4v4.5h4.5\" />\n </Glyph>\n);\nexport const SortGlyph = ({ direction, ...p }: GlyphProps & { direction?: \"ascending\" | \"descending\" }) => (\n <Glyph {...p}>\n {direction === \"ascending\" ? <path d=\"m7 14 5-5 5 5\" /> : direction === \"descending\" ? <path d=\"m7 10 5 5 5-5\" /> : <path d=\"m8 9 4-4 4 4M8 15l4 4 4-4\" />}\n </Glyph>\n);\nexport const ArrowGlyph = ({ direction = \"right\", ...p }: GlyphProps & { direction?: \"left\" | \"right\" }) => (\n <Glyph {...p}>\n <path d={direction === \"left\" ? \"M19 12H5m0 0 6-6m-6 6 6 6\" : \"M5 12h14m0 0-6-6m6 6-6 6\"} />\n </Glyph>\n);\nexport const ExternalGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M14 4h6v6M20 4l-9 9\" />\n <path d=\"M18 14v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4\" />\n </Glyph>\n);\nexport const WarningGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M12 4 2.5 20h19L12 4Z\" />\n <path d=\"M12 10v4M12 17.2v.1\" />\n </Glyph>\n);\nexport const CopyGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\" />\n <path d=\"M15 9V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h3\" />\n </Glyph>\n);\n"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"path": "media.ts",
|
|
179
|
+
"content": "// Shared by the data and media primitives (client): the clock format, the reduced-motion preference, the\n// in-view observer, a debounced callback. Never an entry of its own.\nimport * as React from \"react\";\n\n/** Seconds as a clock: `75` → `1:15`, `3725` → `1:02:05`. Negative or unknown values read `0:00`. */\nexport function formatClock(seconds: number): string {\n const s = Number.isFinite(seconds) && seconds > 0 ? Math.floor(seconds) : 0;\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n const rest = String(s % 60).padStart(2, \"0\");\n return h > 0 ? `${h}:${String(m).padStart(2, \"0\")}:${rest}` : `${m}:${rest}`;\n}\n\n/** Clamps `value` between `min` and `max`. */\nexport const clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\nconst REDUCE = \"(prefers-reduced-motion: reduce)\";\nconst subscribeReduce = (notify: () => void) => {\n if (typeof window === \"undefined\" || !window.matchMedia) return () => undefined;\n const query = window.matchMedia(REDUCE);\n query.addEventListener?.(\"change\", notify);\n return () => query.removeEventListener?.(\"change\", notify);\n};\n\n/** `true` when the person asked for less motion (`prefers-reduced-motion: reduce`); follows a change of the setting. */\nexport function usePrefersReducedMotion(): boolean {\n return React.useSyncExternalStore(\n subscribeReduce,\n () => (typeof window !== \"undefined\" && window.matchMedia ? window.matchMedia(REDUCE).matches : false),\n () => false,\n );\n}\n\n/** The latest value of a callback, for an effect or an event that must not re-subscribe when it changes. */\nexport function useLatest<T>(value: T) {\n const ref = React.useRef(value);\n React.useLayoutEffect(() => {\n ref.current = value;\n });\n return ref;\n}\n\n/** Calls `onChange(visible)` when at least `threshold` of the element enters or leaves the viewport. */\nexport function useInView(ref: React.RefObject<Element | null>, onChange: (visible: boolean) => void, enabled = true, threshold = 0.25) {\n const latest = useLatest(onChange);\n React.useEffect(() => {\n const element = ref.current;\n if (!enabled || !element || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver(([entry]) => entry && latest.current(entry.isIntersecting), { threshold });\n observer.observe(element);\n return () => observer.disconnect();\n }, [ref, enabled, threshold, latest]);\n}\n\n/** A stable function that runs `callback` once `delay` ms have passed without a new call; `cancel()` drops the pending one. */\nexport function useDebouncedCallback<A extends unknown[]>(callback: (...args: A) => void, delay: number) {\n const latest = useLatest(callback);\n const [debounced] = React.useState(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n let wait = delay;\n const run = (...args: A) => {\n clearTimeout(timer);\n if (wait <= 0) latest.current(...args);\n else timer = setTimeout(() => latest.current(...args), wait);\n };\n return Object.assign(run, {\n cancel: () => clearTimeout(timer),\n setDelay: (next: number) => {\n wait = next;\n },\n });\n });\n React.useEffect(() => debounced.setDelay(delay), [debounced, delay]);\n React.useEffect(() => () => debounced.cancel(), [debounced]);\n return debounced;\n}\n\n/** A value controlled by a prop when it is given, held inside otherwise; `set` calls `onChange` either way. */\nexport function useControllable<T>(value: T | undefined, defaultValue: T, onChange?: (next: T) => void) {\n const [inner, setInner] = React.useState(defaultValue);\n const controlled = value !== undefined;\n const current = controlled ? value : inner;\n const set = React.useCallback(\n (next: T) => {\n if (!controlled) setInner(next);\n onChange?.(next);\n },\n [controlled, onChange],\n );\n return [current, set] as const;\n}\n\n/** Starts a media element without an unhandled rejection (autoplay refused, the source replaced meanwhile). */\nexport function playSafely(media: HTMLMediaElement | null | undefined) {\n try {\n const started = media?.play() as Promise<void> | undefined;\n started?.catch?.(() => undefined);\n } catch {\n // Not playable here (no media support): the controls stay as they are.\n }\n}\n"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"path": "meta.ts",
|
|
183
|
+
"content": "// The documentation of a component, carried by its code: each primitive has a `meta.ts` beside its source\n// (`src/<name>/meta.ts`; a component that exists only in React Native: `src/native/meta/<name>.ts`). Never built into\n// the package: `scripts/build-registry.mjs` reads them into `registry/<name>.json`, which krizaka.com renders as\n// /docs/ui/<name>, and `scripts/registry.test.mjs` fails when one is missing or incomplete.\n//\n// Why a typed module and not JSDoc tags: the fields are lists and links (`related`, `whenNotToUse[].use`, examples),\n// which a type checks and a comment does not; the file is plain data (erasable TypeScript), so Node reads it without a\n// compiler, and an editor completes it.\n\n/** Every documented component: the web primitives (one entry of the package each) and the native-only ones. */\nexport type ComponentName =\n | \"achievement\"\n | \"action-bar\"\n | \"activity-feed\"\n | \"action-sheet\"\n | \"alert\"\n | \"app-shell\"\n | \"argument-card\"\n | \"audio-player\"\n | \"auth-layout\"\n | \"avatar\"\n | \"badge\"\n | \"button\"\n | \"card\"\n | \"card-grid\"\n | \"catalogue-page\"\n | \"changelog-page\"\n | \"checkbox\"\n | \"chip\"\n | \"chip-link\"\n | \"choice-grid\"\n | \"cn\"\n | \"code-block\"\n | \"combobox\"\n | \"command\"\n | \"component-page\"\n | \"confirm-button\"\n | \"contact-page\"\n | \"continue-prompt\"\n | \"countdown\"\n | \"cta-panel\"\n | \"dashboard-layout\"\n | \"data-table\"\n | \"date-picker\"\n | \"decision-list\"\n | \"description-list\"\n | \"detail-layout\"\n | \"dialog\"\n | \"docs-article-page\"\n | \"docs-hub-page\"\n | \"docs-layout\"\n | \"dropdown-menu\"\n | \"empty-state\"\n | \"error-page\"\n | \"fab\"\n | \"field\"\n | \"file-upload\"\n | \"filter-bar\"\n | \"form\"\n | \"gallery-page\"\n | \"glow-card\"\n | \"goal-gauge\"\n | \"header\"\n | \"how-it-works-page\"\n | \"image-cropper\"\n | \"image-viewer\"\n | \"iso\"\n | \"kanban\"\n | \"kbd\"\n | \"landing-page\"\n | \"landscape\"\n | \"legal-page\"\n | \"link-card\"\n | \"list\"\n | \"loader\"\n | \"map\"\n | \"longform-page\"\n | \"marketing-layout\"\n | \"marquee\"\n | \"mascot-quote\"\n | \"mascot-state\"\n | \"mascots\"\n | \"media-capture\"\n | \"media-picker\"\n | \"meter\"\n | \"nav-bar\"\n | \"number-ticker\"\n | \"onboarding\"\n | \"otp-input\"\n | \"page\"\n | \"page-header\"\n | \"page-hero\"\n | \"pagination\"\n | \"permission-prompt\"\n | \"pointer-light\"\n | \"popover\"\n | \"pricing-page\"\n | \"product-page\"\n | \"profile-card\"\n | \"progress\"\n | \"promise-card\"\n | \"pull-to-refresh\"\n | \"radio-group\"\n | \"scroll-stage\"\n | \"search-field\"\n | \"section-backdrop\"\n | \"segmented\"\n | \"separator\"\n | \"settings-layout\"\n | \"skeleton\"\n | \"slider\"\n | \"slot\"\n | \"spinner\"\n | \"split-view\"\n | \"stage-banner\"\n | \"stat\"\n | \"status-page\"\n | \"stepper\"\n | \"swipeable-row\"\n | \"switch\"\n | \"tab-bar\"\n | \"tabs\"\n | \"tag-input\"\n | \"terminal-replay\"\n | \"theme\"\n | \"toast\"\n | \"toc\"\n | \"tooltip\"\n | \"tree-view\"\n | \"txt\"\n | \"video-player\"\n | \"video-trimmer\"\n | \"virtual\";\n\n/** Where a component exists: `@krizaka/ui/<name>` (web), `@krizaka/ui/native` (React Native), or both. */\nexport type Platform = \"web\" | \"native\" | \"both\";\n\n/** `stable`: its API only changes in a major. `beta`: it may still change in a minor. */\nexport type Status = \"stable\" | \"beta\";\n\n/**\n * The group of the catalogue. `media`: video, sound, camera, files, cropping. `blocks`: the page blocks — the frame,\n * the hero, sections, cards that lead or argue, decisions, code, calls to act — that every page of a site is made of.\n * `layouts`: the shells of whole screens — an application, a dashboard, settings, sign-in, an object, a list and its\n * item, a site's page, a documentation page — each with its screens. `templates`: the page templates — whole pages of a\n * site (a landing, a product, a docs hub, a long read, a changelog, pricing, status, an error…), each a distinct\n * composition of the blocks, words and content as props.\n */\nexport type Category = \"actions\" | \"forms\" | \"navigation\" | \"overlays\" | \"feedback\" | \"data-display\" | \"media\" | \"blocks\" | \"layouts\" | \"templates\" | \"layout\" | \"foundations\";\n\n/**\n * A named example: the file `registry/examples/<component>/<name>.tsx` (web) or\n * `registry/examples/<component>/native/<name>.tsx` (React Native) — at most 40 lines, imported by the stories and\n * shown (live, with its code) by the documentation.\n */\nexport interface Example {\n /** The file name, kebab-case (`primary`, `icon-button`). */\n readonly name: string;\n /** A short title (`Primary`, `Icon button`). */\n readonly title: string;\n /** One or two sentences: when this variant is the right one. */\n readonly description: string;\n /**\n * A template: a whole screen of a product composed from the platform (a layout and its blocks, real words, its phone\n * version thought out), copied as a starting point — at most 160 lines, listed on krizaka.com/docs/ui/templates.\n */\n readonly template?: boolean;\n}\n\n/** One platform's side of a component. */\nexport interface PlatformDocs {\n /** The names to import (`[\"Button\", \"IconButton\"]`): from `@krizaka/ui/<name>` on the web, `@krizaka/ui/native` in React Native. */\n readonly imports: readonly string[];\n /** The examples, in reading order; the first one is the component's preview. */\n readonly examples: readonly Example[];\n}\n\n/** The React Native side: the same concept, and what differs from the web API. */\nexport interface NativeDocs extends PlatformDocs {\n /**\n * The entry to import from when it is not `@krizaka/ui/native`: a component that needs an Expo module (an optional\n * peer) has its own, `@krizaka/ui/native/<name>`, so an app that does not use it never installs the module.\n */\n readonly entry?: string;\n /** What differs from the web API (`label` instead of children…); empty for a native-only component. */\n readonly differences: readonly string[];\n}\n\nexport interface KeyboardInteraction {\n /** The keys, as written on a keyboard: `Space`, `Enter`, `Arrow keys`, `Esc`, `Tab`. */\n readonly keys: string;\n /** What they do. */\n readonly action: string;\n}\n\nexport interface ComponentMeta {\n /** The display name: `Button`, `Dropdown menu`. */\n readonly title: string;\n /** One sentence: what it is. */\n readonly summary: string;\n readonly status: Status;\n readonly category: Category;\n /** Must match the sides below: `both` ⇔ `web` and `native`. */\n readonly platforms: Platform;\n /** When to reach for it: concrete situations, one per item. */\n readonly whenToUse: readonly string[];\n /** When not to — and what to use instead (`use`), when another component is the answer. */\n readonly whenNotToUse: readonly { readonly when: string; readonly use?: ComponentName }[];\n /** How to use it well: wording, placement, composition. */\n readonly bestPractices: readonly string[];\n readonly accessibility: {\n /** The keyboard, when it does more than Tab and Enter. */\n readonly keyboard: readonly KeyboardInteraction[];\n /** Roles, names and announcements: what the component does, what the app must provide. */\n readonly notes: readonly string[];\n };\n /** The components a reader of this page should know about. */\n readonly related: readonly ComponentName[];\n readonly web?: PlatformDocs;\n readonly native?: NativeDocs;\n}\n"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"path": "tree-view/index.ts",
|
|
187
|
+
"content": "/** @krizaka/ui/tree-view — `TreeView`: a hierarchy the keyboard walks (the ARIA tree), branches loaded on demand. */\nexport { type TreeNode, TreeView, treeView, type TreeViewProps } from \"./tree-view\";\n"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"path": "tree-view/meta.ts",
|
|
191
|
+
"content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Tree view\",\n summary: \"A hierarchy the keyboard walks — the ARIA tree: one tab stop, the arrows move and open, a letter jumps, branches load on demand.\",\n status: \"beta\",\n category: \"navigation\",\n platforms: \"web\",\n whenToUse: [\"The documentation's sections (krizaka.com/docs).\", \"A studio's datasets, folders of files.\"],\n whenNotToUse: [\n { when: \"For two levels or fewer: a list with headings reads better.\", use: \"list\" },\n { when: \"On a phone: drill down screen by screen with a list.\", use: \"list\" },\n ],\n bestPractices: [\"Open the branch of the selected node at first (`defaultExpanded`).\", \"Load big branches on demand (`hasChildren` + `onLoadChildren`).\"],\n accessibility: {\n keyboard: [\n { keys: \"Arrow Down / Arrow Up\", action: \"Move to the next or previous visible node.\" },\n { keys: \"Arrow Right\", action: \"Opens a closed branch, or moves to its first child.\" },\n { keys: \"Arrow Left\", action: \"Closes an open branch, or moves to its parent.\" },\n { keys: \"Home / End\", action: \"Move to the first or last visible node.\" },\n { keys: \"Enter / Space\", action: \"Select the node (`onSelect`).\" },\n { keys: \"A letter\", action: \"Moves to the next node whose name starts with it.\" },\n ],\n notes: [\"`tree`, `treeitem` and `group` with level, position and size; a loading branch is busy.\", \"Web only: a phone drills down with lists.\"],\n },\n related: [\"list\", \"nav-bar\"],\n web: {\n imports: [\"TreeView\"],\n examples: [\n { name: \"docs\", title: \"Documentation\", description: \"Products, sections and pages, the current page selected.\" },\n { name: \"lazy\", title: \"Loaded on demand\", description: \"A branch fetches its files when it opens.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"path": "tree-view/tree-view.tsx",
|
|
195
|
+
"content": "// Client (expansion, selection, the roving focus). A hierarchy the keyboard walks — the ARIA tree pattern: one tab\n// stop, the arrows move and open, Home/End, typing a letter jumps; children loaded on demand when a branch opens.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { ChevronGlyph } from \"../glyphs\";\nimport { useControllable } from \"../media\";\n\nexport const treeView = tv({\n slots: {\n root: \"m-0 list-none p-0 text-sm\",\n group: \"m-0 list-none p-0\",\n row:\n \"flex min-h-8 cursor-pointer select-none items-center gap-1.5 rounded-md pr-2 text-fg outline-hidden \" +\n \"hover:bg-surface-2 data-[selected]:bg-accent-soft data-[selected]:font-semibold data-[disabled]:cursor-default data-[disabled]:opacity-50\",\n toggle: \"flex h-5 w-5 shrink-0 items-center justify-center text-fg-secondary [&>svg]:h-3.5 [&>svg]:w-3.5 [&>svg]:transition-transform motion-reduce:[&>svg]:transition-none\",\n icon: \"flex shrink-0 items-center text-fg-secondary [&>svg]:h-4 [&>svg]:w-4\",\n label: \"min-w-0 flex-1 truncate\",\n meta: \"shrink-0 text-xs tabular-nums text-fg-secondary\",\n },\n});\n\nexport type TreeNode = {\n /** A stable id. */\n id: string;\n /** Its name — passed translated. */\n label: string;\n /** A decorative icon before the name. */\n icon?: React.ReactNode;\n /** A detail after the name (a count, a size). */\n meta?: React.ReactNode;\n /** Its children; `undefined` for a leaf. With `hasChildren`, they load when it opens (`onLoadChildren`). */\n children?: readonly TreeNode[];\n /** A branch whose children are not loaded yet. */\n hasChildren?: boolean;\n /** Cannot be selected. */\n disabled?: boolean;\n};\n\nexport type TreeViewProps = {\n /** The roots. */\n nodes: readonly TreeNode[];\n /** The tree's accessible name (“Documentation”). */\n \"aria-label\": string;\n /** The ids of the open branches (controlled). */\n expanded?: readonly string[];\n /** The ids open at first, uncontrolled. */\n defaultExpanded?: readonly string[];\n /** Called with the open branches. */\n onExpandedChange?: (expanded: string[]) => void;\n /** The selected node (controlled). */\n selected?: string | null;\n /** The selected node at first, uncontrolled. */\n defaultSelected?: string | null;\n /** Called when a node is chosen (click, Enter or Space): navigate, open the file. */\n onSelect?: (node: TreeNode) => void;\n /** Called when a branch with `hasChildren` and no `children` opens: fetch them, then pass them in `nodes`. */\n onLoadChildren?: (node: TreeNode) => void;\n /** The words of a branch that is loading (“Loading”). */\n loadingLabel?: string;\n /** Classes merged on the tree. */\n className?: string;\n};\n\ntype Flat = { node: TreeNode; level: number; parent: string | null; posinset: number; setsize: number };\n\nconst isBranch = (node: TreeNode) => Boolean(node.children?.length || node.hasChildren);\n\nfunction flatten(nodes: readonly TreeNode[], open: Set<string>, level = 1, parent: string | null = null, out: Flat[] = []): Flat[] {\n nodes.forEach((node, i) => {\n out.push({ node, level, parent, posinset: i + 1, setsize: nodes.length });\n if (open.has(node.id) && node.children) flatten(node.children, open, level + 1, node.id, out);\n });\n return out;\n}\n\n/**\n * A hierarchy to browse — documentation sections, a studio's datasets, folders: one tab stop, the arrows walk it (→\n * opens, ← closes or goes up), Home/End, a letter jumps to the next name; branches can load their children on demand.\n */\nexport function TreeView({\n nodes,\n \"aria-label\": label,\n expanded: expandedProp,\n defaultExpanded = [],\n onExpandedChange,\n selected: selectedProp,\n defaultSelected = null,\n onSelect,\n onLoadChildren,\n loadingLabel = \"Loading\",\n className,\n}: TreeViewProps) {\n const s = treeView();\n const uid = React.useId();\n const [expanded, setExpanded] = useControllable<readonly string[]>(expandedProp, defaultExpanded, onExpandedChange as (next: readonly string[]) => void);\n const [selected, setSelected] = useControllable<string | null>(selectedProp, defaultSelected);\n const open = new Set(expanded);\n const rows = flatten(nodes, open);\n const [active, setActive] = React.useState<string | null>(null);\n const focusId = active && rows.some((r) => r.node.id === active) ? active : (selected ?? rows[0]?.node.id ?? null);\n const refs = React.useRef(new Map<string, HTMLDivElement>());\n const move = (id: string | undefined) => {\n if (!id) return;\n setActive(id);\n refs.current.get(id)?.focus();\n };\n const toggle = (node: TreeNode, to = !open.has(node.id)) => {\n if (!isBranch(node)) return;\n if (to && node.hasChildren && !node.children) onLoadChildren?.(node);\n setExpanded(to ? [...expanded, node.id] : expanded.filter((id) => id !== node.id));\n };\n const choose = (node: TreeNode) => {\n if (node.disabled) return;\n setSelected(node.id);\n onSelect?.(node);\n };\n const onKeyDown = (event: React.KeyboardEvent, i: number) => {\n const row = rows[i]!;\n const { node } = row;\n const keys: Record<string, () => void> = {\n ArrowDown: () => move(rows[i + 1]?.node.id),\n ArrowUp: () => move(rows[i - 1]?.node.id),\n Home: () => move(rows[0]?.node.id),\n End: () => move(rows[rows.length - 1]?.node.id),\n ArrowRight: () => (isBranch(node) && !open.has(node.id) ? toggle(node, true) : isBranch(node) ? move(rows[i + 1]?.node.id) : undefined),\n ArrowLeft: () => (open.has(node.id) ? toggle(node, false) : move(row.parent ?? undefined)),\n Enter: () => choose(node),\n \" \": () => choose(node),\n };\n const run = keys[event.key];\n if (run) {\n event.preventDefault();\n run();\n return;\n }\n if (event.key.length === 1 && /\\S/.test(event.key)) {\n const letter = event.key.toLowerCase();\n const next = [...rows.slice(i + 1), ...rows.slice(0, i)].find((r) => r.node.label.toLowerCase().startsWith(letter));\n move(next?.node.id);\n }\n };\n\n const render = (list: readonly TreeNode[], level: number): React.ReactNode =>\n list.map((node) => {\n const i = rows.findIndex((r) => r.node.id === node.id);\n const row = rows[i]!;\n const branch = isBranch(node);\n const isOpen = open.has(node.id);\n const loading = isOpen && node.hasChildren && !node.children;\n return (\n // The row is the treeitem (its name is its own words, never its children's); the group of children hangs\n // from it with aria-owns, in the `li` that holds both.\n <li key={node.id} role=\"none\">\n <div\n ref={(el) => {\n if (el) refs.current.set(node.id, el);\n else refs.current.delete(node.id);\n }}\n role=\"treeitem\"\n aria-level={level}\n aria-posinset={row.posinset}\n aria-setsize={row.setsize}\n aria-expanded={branch ? isOpen : undefined}\n aria-selected={selected === node.id}\n aria-disabled={node.disabled || undefined}\n aria-busy={loading || undefined}\n aria-owns={branch && isOpen ? `${uid}-${node.id}-group` : undefined}\n tabIndex={node.id === focusId ? 0 : -1}\n onKeyDown={(e) => {\n if (e.target === e.currentTarget) onKeyDown(e, i);\n }}\n onFocus={(e) => {\n if (e.target === e.currentTarget) setActive(node.id);\n }}\n className={s.row({ className: \"outline-hidden focus-visible:ring-2 focus-visible:ring-ring\" })}\n data-selected={selected === node.id || undefined}\n data-disabled={node.disabled || undefined}\n style={{ paddingLeft: `${(level - 1) * 1.25 + 0.25}rem` }}\n onClick={() => {\n if (branch) toggle(node);\n choose(node);\n move(node.id);\n }}\n >\n <span className={s.toggle()} aria-hidden>\n {branch ? <ChevronGlyph direction={isOpen ? \"down\" : \"right\"} /> : null}\n </span>\n {node.icon ? <span className={s.icon()} aria-hidden>{node.icon}</span> : null}\n <span className={s.label()}>{node.label}</span>\n {node.meta ? <span className={s.meta()}>{node.meta}</span> : null}\n </div>\n {branch && isOpen ? (\n <ul role=\"group\" id={`${uid}-${node.id}-group`} className={s.group()}>\n {loading ? (\n <li role=\"none\" className=\"py-1 text-xs text-fg-secondary\" style={{ paddingLeft: `${level * 1.25 + 1.75}rem` }}>\n {loadingLabel}\n </li>\n ) : (\n render(node.children ?? [], level + 1)\n )}\n </ul>\n ) : null}\n </li>\n );\n });\n\n return (\n <ul role=\"tree\" aria-label={label} className={s.root({ className })}>\n {render(nodes, 1)}\n </ul>\n );\n}\n"
|
|
196
|
+
}
|
|
197
|
+
],
|
|
198
|
+
"dependencies": [
|
|
199
|
+
"tailwind-variants@^3.3.1"
|
|
200
|
+
],
|
|
201
|
+
"registryDependencies": [],
|
|
202
|
+
"demo": {
|
|
203
|
+
"path": "examples/tree-view/docs.tsx",
|
|
204
|
+
"content": "\"use client\";\n\nimport { TreeView } from \"@krizaka/ui/tree-view\";\n\nconst nodes = [\n {\n id: \"orazaka\",\n label: \"Orazaka\",\n children: [\n { id: \"getting-started\", label: \"Getting started\" },\n { id: \"studios\", label: \"Studios\", meta: \"12\", children: [{ id: \"dubbing\", label: \"Dubbing\" }, { id: \"transcript\", label: \"Transcript\" }, { id: \"clips\", label: \"Clips\" }] },\n { id: \"api\", label: \"API reference\" },\n ],\n },\n { id: \"orochia\", label: \"Orochia\", children: [{ id: \"auctions\", label: \"Auctions\" }, { id: \"challenges\", label: \"Challenges\" }] },\n { id: \"ui\", label: \"Krizaka UI\", children: [{ id: \"components\", label: \"Components\" }] },\n];\n\n// The documentation's sections: one tab stop, the arrows walk and open, a letter jumps.\nexport default function TreeViewDocs() {\n return <TreeView aria-label=\"Documentation\" nodes={nodes} defaultExpanded={[\"orazaka\", \"studios\"]} defaultSelected=\"dubbing\" className=\"max-w-xs\" />;\n}\n"
|
|
205
|
+
},
|
|
206
|
+
"props": [
|
|
207
|
+
{
|
|
208
|
+
"component": "TreeView",
|
|
209
|
+
"description": "A hierarchy to browse — documentation sections, a studio's datasets, folders: one tab stop, the arrows walk it (→\nopens, ← closes or goes up), Home/End, a letter jumps to the next name; branches can load their children on demand.",
|
|
210
|
+
"props": [
|
|
211
|
+
{
|
|
212
|
+
"name": "aria-label",
|
|
213
|
+
"type": "string",
|
|
214
|
+
"default": null,
|
|
215
|
+
"description": "The tree's accessible name (“Documentation”).",
|
|
216
|
+
"required": true
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"name": "nodes",
|
|
220
|
+
"type": "readonly TreeNode[]",
|
|
221
|
+
"default": null,
|
|
222
|
+
"description": "The roots.",
|
|
223
|
+
"required": true
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"name": "className",
|
|
227
|
+
"type": "string",
|
|
228
|
+
"default": null,
|
|
229
|
+
"description": "Classes merged on the tree.",
|
|
230
|
+
"required": false
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"name": "defaultExpanded",
|
|
234
|
+
"type": "readonly string[]",
|
|
235
|
+
"default": "[]",
|
|
236
|
+
"description": "The ids open at first, uncontrolled.",
|
|
237
|
+
"required": false
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"name": "defaultSelected",
|
|
241
|
+
"type": "string | null",
|
|
242
|
+
"default": "null",
|
|
243
|
+
"description": "The selected node at first, uncontrolled.",
|
|
244
|
+
"required": false
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"name": "expanded",
|
|
248
|
+
"type": "readonly string[]",
|
|
249
|
+
"default": null,
|
|
250
|
+
"description": "The ids of the open branches (controlled).",
|
|
251
|
+
"required": false
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"name": "loadingLabel",
|
|
255
|
+
"type": "string",
|
|
256
|
+
"default": "Loading",
|
|
257
|
+
"description": "The words of a branch that is loading (“Loading”).",
|
|
258
|
+
"required": false
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"name": "onExpandedChange",
|
|
262
|
+
"type": "((expanded: string[]) => void)",
|
|
263
|
+
"default": null,
|
|
264
|
+
"description": "Called with the open branches.",
|
|
265
|
+
"required": false
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"name": "onLoadChildren",
|
|
269
|
+
"type": "((node: TreeNode) => void)",
|
|
270
|
+
"default": null,
|
|
271
|
+
"description": "Called when a branch with `hasChildren` and no `children` opens: fetch them, then pass them in `nodes`.",
|
|
272
|
+
"required": false
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"name": "onSelect",
|
|
276
|
+
"type": "((node: TreeNode) => void)",
|
|
277
|
+
"default": null,
|
|
278
|
+
"description": "Called when a node is chosen (click, Enter or Space): navigate, open the file.",
|
|
279
|
+
"required": false
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"name": "selected",
|
|
283
|
+
"type": "string | null",
|
|
284
|
+
"default": null,
|
|
285
|
+
"description": "The selected node (controlled).",
|
|
286
|
+
"required": false
|
|
287
|
+
}
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
]
|
|
291
|
+
}
|