@krizaka/ui 3.22.0 → 3.24.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/README.md +6 -1
- package/dist/achievement.js +1 -1
- package/dist/action-bar.js +4 -4
- package/dist/app-header.d.ts +79 -0
- package/dist/app-header.js +32 -0
- package/dist/app-header.js.map +1 -0
- package/dist/app-shell.d.ts +20 -2
- package/dist/app-shell.js +34 -19
- package/dist/app-shell.js.map +1 -1
- package/dist/argument-card.d.ts +4 -1
- package/dist/argument-card.js +10 -7
- package/dist/argument-card.js.map +1 -1
- package/dist/audio-player.d.ts +3 -2
- package/dist/audio-player.js +14 -10
- package/dist/audio-player.js.map +1 -1
- package/dist/blocks.css +28 -0
- package/dist/button.js +2 -1
- package/dist/captcha.d.ts +81 -0
- package/dist/captcha.js +162 -0
- package/dist/captcha.js.map +1 -0
- package/dist/card-grid.d.ts +10 -1
- package/dist/card-grid.js +3 -2
- package/dist/card-grid.js.map +1 -1
- package/dist/card.js +3 -3
- package/dist/changelog-page.d.ts +57 -3
- package/dist/changelog-page.js +117 -1
- package/dist/changelog-page.js.map +1 -1
- package/dist/choice-grid.js +1 -1
- package/dist/{chunk-YCIBJ6OQ.js → chunk-4DH2HW3D.js} +3 -1
- package/dist/{chunk-3IN6TOPM.js → chunk-6ZYRUOTA.js} +6 -3
- package/dist/chunk-6ZYRUOTA.js.map +1 -0
- package/dist/chunk-APNIVNIX.js +54 -0
- package/dist/chunk-APNIVNIX.js.map +1 -0
- package/dist/{chunk-FKBHWS4N.js → chunk-CEJDH6SA.js} +2 -2
- package/dist/{chunk-OWC2LZD2.js → chunk-CHOJUCVE.js} +6 -3
- package/dist/chunk-CHOJUCVE.js.map +1 -0
- package/dist/{chunk-3BC4XQ6C.js → chunk-DZU6RMYD.js} +6 -3
- package/dist/chunk-DZU6RMYD.js.map +1 -0
- package/dist/{chunk-R6NK6ZNY.js → chunk-F7FVPPBB.js} +4 -4
- package/dist/{chunk-2L67YTNV.js → chunk-FTX66XZY.js} +2 -2
- package/dist/{chunk-5Z7FWCV2.js → chunk-HBZPJ3EP.js} +2 -2
- package/dist/{chunk-C2BRIFJG.js → chunk-HJFRHYCI.js} +2 -2
- package/dist/{chunk-ZNMFG62E.js → chunk-KH3JOEPY.js} +3 -2
- package/dist/chunk-KH3JOEPY.js.map +1 -0
- package/dist/{chunk-BTMFZ66D.js → chunk-KM6VAKIE.js} +2 -2
- package/dist/{chunk-DGQMDJXK.js → chunk-LZNZLCOE.js} +2 -2
- package/dist/{chunk-AQSZJJAJ.js → chunk-MQPC3P4T.js} +2 -2
- package/dist/{chunk-2FRWNSRO.js → chunk-NSLXEDIS.js} +3 -2
- package/dist/chunk-NSLXEDIS.js.map +1 -0
- package/dist/{chunk-4LOMIQVX.js → chunk-W675RFOA.js} +3 -2
- package/dist/chunk-W675RFOA.js.map +1 -0
- package/dist/{chunk-G3ETON2A.js → chunk-WU4VLSEA.js} +3 -2
- package/dist/chunk-WU4VLSEA.js.map +1 -0
- package/dist/{chunk-IZ7MV6HM.js → chunk-XVFQZ3ZG.js} +3 -2
- package/dist/chunk-XVFQZ3ZG.js.map +1 -0
- package/dist/cn.js +1 -1
- package/dist/code-block.js +2 -2
- package/dist/code-block.js.map +1 -1
- package/dist/command.js +3 -3
- package/dist/comparison-table.js +1 -1
- package/dist/confirm-button.js +2 -2
- package/dist/continue-prompt.js +3 -3
- package/dist/continue-prompt.js.map +1 -1
- package/dist/cta-panel.js +1 -1
- package/dist/data-table.js +4 -4
- package/dist/date-picker.js +2 -2
- package/dist/decision-list.js +1 -1
- package/dist/dialog.js +3 -2
- package/dist/dialog.js.map +1 -1
- package/dist/docs-nav.d.ts +36 -0
- package/dist/docs-nav.js +44 -0
- package/dist/docs-nav.js.map +1 -0
- package/dist/dropdown-menu.js +1 -1
- package/dist/error-page.js +1 -1
- package/dist/field.js +1 -1
- package/dist/filter-bar.js +2 -2
- package/dist/force-update-screen.js +2 -1
- package/dist/force-update-screen.js.map +1 -1
- package/dist/gallery-page.js +1 -1
- package/dist/genui.d.ts +3 -1
- package/dist/genui.js +33 -6
- package/dist/genui.js.map +1 -1
- package/dist/glow-card.js +1 -1
- package/dist/goal-gauge.js +1 -1
- package/dist/how-it-works-page.js +1 -1
- package/dist/image-cropper.js +3 -3
- package/dist/index.d.ts +15 -1
- package/dist/index.js +65 -5
- package/dist/index.js.map +1 -1
- package/dist/landscape.js +1 -1
- package/dist/link-card.d.ts +9 -2
- package/dist/link-card.js +5 -44
- package/dist/link-card.js.map +1 -1
- package/dist/longform-page.js +1 -1
- package/dist/maintenance-screen.js +2 -1
- package/dist/maintenance-screen.js.map +1 -1
- package/dist/map.js +3 -3
- package/dist/map.js.map +1 -1
- package/dist/markdown.js +2 -1
- package/dist/markdown.js.map +1 -1
- package/dist/marquee.js +1 -1
- package/dist/mascot-quote.js +1 -1
- package/dist/match-dialog.js +2 -1
- package/dist/match-dialog.js.map +1 -1
- package/dist/media-grid.d.ts +26 -4
- package/dist/media-grid.js +144 -77
- package/dist/media-grid.js.map +1 -1
- package/dist/native/map.js +3 -3
- package/dist/native/map.js.map +1 -1
- package/dist/native.d.ts +18 -1
- package/dist/native.js +105 -24
- package/dist/native.js.map +1 -1
- package/dist/nav-bar.js +3 -3
- package/dist/page-hero.js +6 -6
- package/dist/page.js +2 -2
- package/dist/popover.js +1 -1
- package/dist/pricing-page.js +1 -1
- package/dist/product-page.js +1 -1
- package/dist/profile-card.js +1 -1
- package/dist/promise-card.js +1 -1
- package/dist/radio-group.js +2 -2
- package/dist/rail-nav.d.ts +149 -0
- package/dist/rail-nav.js +177 -0
- package/dist/rail-nav.js.map +1 -0
- package/dist/scroll-stage.js +1 -1
- package/dist/settings-layout.d.ts +75 -62
- package/dist/settings-layout.js +39 -6
- package/dist/settings-layout.js.map +1 -1
- package/dist/showcase.js +1 -1
- package/dist/site-footer.d.ts +48 -67
- package/dist/site-footer.js +36 -12
- package/dist/site-footer.js.map +1 -1
- package/dist/slider.js +2 -2
- package/dist/stage-banner.js +1 -1
- package/dist/step-showcase.js +1 -1
- package/dist/tabs.js +1 -1
- package/dist/tabs.js.map +1 -1
- package/dist/terminal-replay.js +1 -1
- package/dist/theme.js +2 -1
- package/dist/theme.js.map +1 -1
- package/dist/toast.js +1 -1
- package/dist/toc.js +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/update-prompt.js +2 -1
- package/dist/update-prompt.js.map +1 -1
- package/dist/vertical-video.js +2 -2
- package/dist/video-player.js +3 -3
- package/dist/waveform.d.ts +93 -0
- package/dist/waveform.js +95 -0
- package/dist/waveform.js.map +1 -0
- package/package.json +81 -10
- package/registry/achievement.json +1 -1
- package/registry/action-bar.json +1 -1
- package/registry/activity-feed.json +1 -1
- package/registry/alert.json +1 -1
- package/registry/app-header.json +202 -0
- package/registry/app-shell.json +33 -9
- package/registry/argument-card.json +37 -5
- package/registry/audio-player.json +5 -3
- package/registry/auth-layout.json +1 -1
- package/registry/avatar.json +1 -1
- package/registry/badge.json +1 -1
- package/registry/button.json +3 -2
- package/registry/captcha.json +300 -0
- package/registry/card-grid.json +27 -3
- package/registry/card.json +1 -1
- package/registry/catalogue-page.json +1 -1
- package/registry/changelog-page.json +11 -7
- package/registry/chat.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/cn.json +1 -1
- package/registry/code-block.json +1 -1
- package/registry/combobox.json +1 -1
- package/registry/command.json +1 -1
- package/registry/comparison-table.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 +1 -1
- package/registry/decision-list.json +1 -1
- package/registry/description-list.json +1 -1
- 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/docs-nav.json +177 -0
- package/registry/document-viewer.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/activity-feed/native/notifications.light.png +0 -0
- package/registry/examples/app-header/basic.d.ts +4 -0
- package/registry/examples/app-header/basic.js +23 -0
- package/registry/examples/app-header/basic.tsx +17 -0
- package/registry/examples/app-shell/desktop.d.ts +4 -0
- package/registry/examples/app-shell/desktop.js +41 -0
- package/registry/examples/app-shell/desktop.tsx +37 -0
- package/registry/examples/argument-card/hover-light.d.ts +4 -0
- package/registry/examples/argument-card/hover-light.js +17 -0
- package/registry/examples/argument-card/hover-light.tsx +19 -0
- package/registry/examples/argument-card/hover-quiet.d.ts +4 -0
- package/registry/examples/argument-card/hover-quiet.js +17 -0
- package/registry/examples/argument-card/hover-quiet.tsx +19 -0
- package/registry/examples/avatar/native/group.light.png +0 -0
- package/registry/examples/avatar/native/presence.light.png +0 -0
- package/registry/examples/avatar/native/sizes.light.png +0 -0
- package/registry/examples/badge/native/tones.light.png +0 -0
- package/registry/examples/button/native/ghost.light.png +0 -0
- package/registry/examples/captcha/disclosure.d.ts +4 -0
- package/registry/examples/captcha/disclosure.js +14 -0
- package/registry/examples/captcha/disclosure.tsx +11 -0
- package/registry/examples/captcha/form.d.ts +4 -0
- package/registry/examples/captcha/form.js +18 -0
- package/registry/examples/captcha/form.tsx +17 -0
- package/registry/examples/card/native/body.light.png +0 -0
- package/registry/examples/card/native/default.light.png +0 -0
- package/registry/examples/card/native/elevated.light.png +0 -0
- package/registry/examples/card/native/pressable.light.png +0 -0
- package/registry/examples/card-grid/hover-quiet.d.ts +4 -0
- package/registry/examples/card-grid/hover-quiet.js +18 -0
- package/registry/examples/card-grid/hover-quiet.tsx +20 -0
- package/registry/examples/changelog-page/releases.js +1 -1
- package/registry/examples/changelog-page/releases.tsx +1 -1
- package/registry/examples/chat/native/conversation.light.png +0 -0
- package/registry/examples/chat/native/inbox.light.png +0 -0
- package/registry/examples/chip/native/multiple.light.png +0 -0
- package/registry/examples/chip/native/removable.light.png +0 -0
- package/registry/examples/chip/native/single.light.png +0 -0
- package/registry/examples/chip/native/toggle.light.png +0 -0
- package/registry/examples/combobox/native/multiple.light.png +0 -0
- package/registry/examples/combobox/native/search.light.png +0 -0
- package/registry/examples/countdown/native/days.light.png +0 -0
- package/registry/examples/countdown/native/hours.light.png +0 -0
- package/registry/examples/countdown/native/sizes.light.png +0 -0
- package/registry/examples/countdown/native/urgent.light.png +0 -0
- package/registry/examples/countdown/native/with-label.light.png +0 -0
- package/registry/examples/date-picker/native/birth-date-wheel.light.png +0 -0
- package/registry/examples/date-picker/native/birth-date.light.png +0 -0
- package/registry/examples/date-picker/native/calendar.dark.png +0 -0
- package/registry/examples/date-picker/native/calendar.light.png +0 -0
- package/registry/examples/date-picker/native/day-strip.dark.png +0 -0
- package/registry/examples/date-picker/native/day-strip.light.png +0 -0
- package/registry/examples/date-picker/native/time-slots.dark.png +0 -0
- package/registry/examples/date-picker/native/time-slots.light.png +0 -0
- package/registry/examples/date-picker/native/time-wheel.light.png +0 -0
- package/registry/examples/description-list/native/job-details.light.png +0 -0
- package/registry/examples/docs-nav/groups.d.ts +4 -0
- package/registry/examples/docs-nav/groups.js +21 -0
- package/registry/examples/docs-nav/groups.tsx +15 -0
- package/registry/examples/empty-state/native/default.light.png +0 -0
- package/registry/examples/field/native/default.light.png +0 -0
- package/registry/examples/field/native/select.light.png +0 -0
- package/registry/examples/force-update-screen/native/default.light.png +0 -0
- package/registry/examples/form/native/amount.light.png +0 -0
- package/registry/examples/form/native/audience.light.png +0 -0
- package/registry/examples/form/native/profile.light.png +0 -0
- package/registry/examples/form/native/settings.light.png +0 -0
- package/registry/examples/form/native/sign-up.light.png +0 -0
- package/registry/examples/form/native/upload.dark.png +0 -0
- package/registry/examples/form/native/upload.light.png +0 -0
- package/registry/examples/goal-gauge/native/default.light.png +0 -0
- package/registry/examples/header/native/large-title.light.png +0 -0
- package/registry/examples/link-card/hover-light.d.ts +4 -0
- package/registry/examples/link-card/hover-light.js +18 -0
- package/registry/examples/link-card/hover-light.tsx +20 -0
- package/registry/examples/link-card/hover-quiet.d.ts +4 -0
- package/registry/examples/link-card/hover-quiet.js +18 -0
- package/registry/examples/link-card/hover-quiet.tsx +20 -0
- package/registry/examples/loader/native/job-wait.light.png +0 -0
- package/registry/examples/maintenance-screen/native/default.light.png +0 -0
- package/registry/examples/map/native/places.light.png +0 -0
- package/registry/examples/markdown/native/basic.light.png +0 -0
- package/registry/examples/mascot-state/native/default.light.png +0 -0
- package/registry/examples/media-picker/native/story.light.png +0 -0
- package/registry/examples/meta-row/native/video.light.png +0 -0
- package/registry/examples/meter/native/credits.light.png +0 -0
- package/registry/examples/meter/native/split-ring.light.png +0 -0
- package/registry/examples/number-ticker/native/balance.light.png +0 -0
- package/registry/examples/onboarding/native/first-launch.light.png +0 -0
- package/registry/examples/otp-input/native/verify.light.png +0 -0
- package/registry/examples/pagination/native/cursor.light.png +0 -0
- package/registry/examples/pagination/native/pages.light.png +0 -0
- package/registry/examples/permission-prompt/native/blocked.light.png +0 -0
- package/registry/examples/permission-prompt/native/camera.light.png +0 -0
- package/registry/examples/profile-card/native/default.light.png +0 -0
- package/registry/examples/radio-group/native/buttons.light.png +0 -0
- package/registry/examples/radio-group/native/cards.light.png +0 -0
- package/registry/examples/radio-group/native/list.light.png +0 -0
- package/registry/examples/radio-group/native/segmented.light.png +0 -0
- package/registry/examples/rail-nav/expandable.d.ts +4 -0
- package/registry/examples/rail-nav/expandable.js +34 -0
- package/registry/examples/rail-nav/expandable.tsx +28 -0
- package/registry/examples/rail-nav/studio.d.ts +4 -0
- package/registry/examples/rail-nav/studio.js +43 -0
- package/registry/examples/rail-nav/studio.tsx +38 -0
- package/registry/examples/screen/native/app-shell.light.png +0 -0
- package/registry/examples/screen/native/auth.light.png +0 -0
- package/registry/examples/screen/native/map.light.png +0 -0
- package/registry/examples/screen/native/notifications.light.png +0 -0
- package/registry/examples/screen/native/profile.light.png +0 -0
- package/registry/examples/segmented/native/default.light.png +0 -0
- package/registry/examples/segmented/native/small.light.png +0 -0
- package/registry/examples/settings-layout/flat.d.ts +4 -0
- package/registry/examples/settings-layout/flat.js +26 -0
- package/registry/examples/settings-layout/flat.tsx +30 -0
- package/registry/examples/showcase/native/slides.light.png +0 -0
- package/registry/examples/site-footer/app.d.ts +4 -0
- package/registry/examples/site-footer/app.js +25 -0
- package/registry/examples/site-footer/app.tsx +22 -0
- package/registry/examples/site-footer/docs.d.ts +4 -0
- package/registry/examples/site-footer/docs.js +31 -0
- package/registry/examples/site-footer/docs.tsx +24 -0
- package/registry/examples/slider/native/default.light.png +0 -0
- package/registry/examples/slider/native/stepped.light.png +0 -0
- package/registry/examples/step-progress/native/sign-up.light.png +0 -0
- package/registry/examples/stepper/native/run.light.png +0 -0
- package/registry/examples/swipeable-row/native/conversation.light.png +0 -0
- package/registry/examples/switch/native/settings.light.png +0 -0
- package/registry/examples/tab-bar/native/main-sections.light.png +0 -0
- package/registry/examples/tabs/native/sections.light.png +0 -0
- package/registry/examples/tabs/native/segmented.light.png +0 -0
- package/registry/examples/tag-selector/native/interests.light.png +0 -0
- package/registry/examples/toast/native/tones.light.png +0 -0
- package/registry/examples/txt/native/tones.dark.png +0 -0
- package/registry/examples/txt/native/tones.light.png +0 -0
- package/registry/examples/update-prompt/native/default.light.png +0 -0
- package/registry/examples/waveform/card.d.ts +4 -0
- package/registry/examples/waveform/card.js +18 -0
- package/registry/examples/waveform/card.tsx +16 -0
- package/registry/examples/waveform/native/card.d.ts +4 -0
- package/registry/examples/waveform/native/card.dark.png +0 -0
- package/registry/examples/waveform/native/card.js +19 -0
- package/registry/examples/waveform/native/card.light.png +0 -0
- package/registry/examples/waveform/native/card.tsx +19 -0
- package/registry/examples/waveform/sizes.d.ts +4 -0
- package/registry/examples/waveform/sizes.js +16 -0
- package/registry/examples/waveform/sizes.tsx +14 -0
- package/registry/field.json +1 -1
- package/registry/file-upload.json +1 -1
- package/registry/filter-bar.json +1 -1
- package/registry/force-update-screen.json +1 -1
- package/registry/form.json +1 -1
- package/registry/gallery-page.json +1 -1
- package/registry/genui.json +3 -3
- package/registry/glow-card.json +1 -1
- package/registry/goal-gauge.json +1 -1
- package/registry/how-it-works-page.json +1 -1
- package/registry/image-cropper.json +1 -1
- package/registry/index.json +197 -14
- package/registry/iso.json +1 -1
- package/registry/kanban.json +1 -1
- 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 +38 -6
- package/registry/list.json +1 -1
- package/registry/loader.json +1 -1
- package/registry/longform-page.json +1 -1
- package/registry/maintenance-screen.json +1 -1
- package/registry/map.json +2 -2
- package/registry/markdown.json +1 -1
- 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/match-dialog.json +1 -1
- package/registry/media-capture.json +1 -1
- package/registry/media-grid.json +92 -6
- package/registry/meta-row.json +1 -1
- package/registry/meter.json +1 -1
- package/registry/nav-bar.json +2 -2
- package/registry/number-ticker.json +1 -1
- 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/photo-grid.json +1 -1
- 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 +1 -1
- package/registry/promise-card.json +1 -1
- package/registry/radio-group.json +1 -1
- package/registry/rail-nav.json +493 -0
- package/registry/recipes.json +1 -1
- package/registry/scroll-stage.json +1 -1
- package/registry/search-field.json +1 -1
- package/registry/section-backdrop.json +1 -1
- package/registry/separator.json +1 -1
- package/registry/settings-layout.json +104 -9
- package/registry/showcase.json +1 -1
- package/registry/site-footer.json +38 -6
- package/registry/sites.json +1 -1
- package/registry/skeleton.json +1 -1
- package/registry/skip-link.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 +1 -1
- package/registry/status-page.json +1 -1
- package/registry/step-progress.json +1 -1
- package/registry/step-showcase.json +1 -1
- package/registry/stepper.json +1 -1
- package/registry/swipe-deck.json +1 -1
- package/registry/switch.json +1 -1
- package/registry/tabs.json +2 -2
- package/registry/tag-input.json +1 -1
- package/registry/tag-selector.json +1 -1
- package/registry/terminal-replay.json +1 -1
- package/registry/theme.json +1 -1
- package/registry/toast.json +1 -1
- package/registry/toc.json +1 -1
- package/registry/tooltip.json +1 -1
- package/registry/tree-view.json +1 -1
- package/registry/update-prompt.json +1 -1
- package/registry/verified-badge.json +1 -1
- package/registry/vertical-video.json +1 -1
- package/registry/video-player.json +1 -1
- package/registry/video-trimmer.json +1 -1
- package/registry/virtual.json +1 -1
- package/registry/waveform.json +296 -0
- package/dist/chunk-2FRWNSRO.js.map +0 -1
- package/dist/chunk-3BC4XQ6C.js.map +0 -1
- package/dist/chunk-3IN6TOPM.js.map +0 -1
- package/dist/chunk-4LOMIQVX.js.map +0 -1
- package/dist/chunk-G3ETON2A.js.map +0 -1
- package/dist/chunk-IZ7MV6HM.js.map +0 -1
- package/dist/chunk-OWC2LZD2.js.map +0 -1
- package/dist/chunk-ZNMFG62E.js.map +0 -1
- /package/dist/{chunk-YCIBJ6OQ.js.map → chunk-4DH2HW3D.js.map} +0 -0
- /package/dist/{chunk-FKBHWS4N.js.map → chunk-CEJDH6SA.js.map} +0 -0
- /package/dist/{chunk-R6NK6ZNY.js.map → chunk-F7FVPPBB.js.map} +0 -0
- /package/dist/{chunk-2L67YTNV.js.map → chunk-FTX66XZY.js.map} +0 -0
- /package/dist/{chunk-5Z7FWCV2.js.map → chunk-HBZPJ3EP.js.map} +0 -0
- /package/dist/{chunk-C2BRIFJG.js.map → chunk-HJFRHYCI.js.map} +0 -0
- /package/dist/{chunk-BTMFZ66D.js.map → chunk-KM6VAKIE.js.map} +0 -0
- /package/dist/{chunk-DGQMDJXK.js.map → chunk-LZNZLCOE.js.map} +0 -0
- /package/dist/{chunk-AQSZJJAJ.js.map → chunk-MQPC3P4T.js.map} +0 -0
package/dist/site-footer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/site-footer/site-footer.tsx"],"sourcesContent":["// Client (the marks hold an id). The footer shared by every site of the Krizaka family: the site's own columns, then the\n// family in columns from `@krizaka/ui/sites` (the same groups as the bar's switcher), then the signature line — “A\n// Krizaka product” by the kind of the current site — the version and the place.\nimport { Slot } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { FamilyMark } from \"../family-mark\";\nimport { KrizakaLogo } from \"../marks/KrizakaLogo\";\nimport { type FamilyLabels, familyLabels, siteById, type SiteId, sitesByGroup } from \"../sites/sites\";\n\nexport const siteFooter = tv({\n slots: {\n root: \"w-full border-t border-border-subtle bg-surface-0 text-fg\",\n inner: \"mx-auto grid w-full max-w-(--kz-page-max,72rem) grid-cols-[minmax(0,1fr)] gap-10 px-(--kz-page-gutter,16px) py-12\",\n top: \"grid grid-cols-[minmax(0,1fr)] gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(0,2fr)]\",\n site: \"grid content-start gap-3\",\n siteName: \"inline-flex items-center gap-2 font-display text-[15px] font-bold tracking-tight text-fg\",\n siteText: \"max-w-xs text-sm leading-relaxed text-fg-secondary\",\n own: \"grid grid-cols-2 gap-8 sm:grid-cols-3\",\n family: \"grid grid-cols-2 gap-8 border-t border-border-subtle pt-8 md:grid-cols-4\",\n column: \"grid min-w-0 content-start gap-3\",\n title: \"text-[11px] font-semibold uppercase tracking-wider text-fg-secondary\",\n list: \"grid min-w-0 gap-2\",\n link:\n \"inline-flex min-h-6 min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5 rounded-md text-sm [overflow-wrap:anywhere] text-fg-secondary no-underline transition-colors hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg aria-[current=true]:text-fg aria-[current=true]:font-semibold\",\n mark: \"flex h-4 w-4 shrink-0 items-center justify-center text-fg\",\n tag: \"rounded-full bg-surface-3 px-1.5 py-px text-[10px] font-semibold uppercase tracking-wider text-fg-secondary\",\n bottom: \"flex flex-wrap items-center gap-x-5 gap-y-3 border-t border-border-subtle pt-6 text-xs text-fg-secondary\",\n signature:\n \"inline-flex items-center gap-2 rounded-md font-medium text-fg no-underline hover:text-fg-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n version:\n \"rounded-full border border-border-subtle bg-surface-2 px-2 py-0.5 font-mono text-[11px] text-fg-secondary\",\n legal: \"flex flex-wrap items-center gap-x-4 gap-y-2 sm:ml-auto\",\n },\n});\nconst s = siteFooter();\n\nexport type SiteFooterProps = Omit<React.ComponentProps<\"footer\">, \"children\"> & {\n /** The site this footer belongs to (`@krizaka/ui/sites`): its mark and line, its signature, marked in the family. */\n current: SiteId;\n /**\n * The family's words, passed translated: `familyLabels.fr` from `@krizaka/ui/sites`, or your own of the same shape.\n * @default familyLabels.en\n */\n labels?: FamilyLabels;\n /** The site's own columns (`SiteFooter.Column`), before the family. */\n children?: React.ReactNode;\n /** The version the site runs (`1.2.3`, shown `v1.2.3`). */\n version?: string;\n /** The environment, when it is not production (`DEV`). */\n env?: string;\n /**\n * Shows the family in columns (the Krizaka sites: www, ui., java.). A product is independent once deployed: pass\n * `family={false}` and the footer holds only its own columns, the legal links, the version and one publisher line —\n * “A Krizaka product”, linking to www.krizaka.com.\n * @default true\n */\n family?: boolean;\n /** The end of the signature line: legal links, a language switch (`SiteFooter.Link`s or any inline content). */\n legal?: React.ReactNode;\n};\n\n/** The footer of a Krizaka site: its own columns, the family in columns, the signature, the version, Montréal. */\nexport function SiteFooter({\n current,\n labels = familyLabels.en,\n children,\n version,\n env,\n legal,\n family = true,\n className,\n ...props\n}: SiteFooterProps) {\n const id = React.useId();\n const site = siteById(current);\n const krizaka = siteById(\"krizaka\");\n const tag = [env, version && `v${version.replace(/^v/, \"\")}`].filter(Boolean).join(\" · \");\n return (\n <footer className={s.root({ className })} {...props}>\n <div className={s.inner()}>\n <div className={s.top()}>\n <div className={s.site()}>\n <a href={site.url} className={s.siteName()}>\n <FamilyMark mark={site.mark} size={24} />\n {site.name}\n </a>\n <p className={s.siteText()}>{labels.descriptions[site.id]}</p>\n </div>\n {children && <div className={s.own()}>{children}</div>}\n </div>\n {family && (\n <nav aria-label={labels.family} className={s.family()}>\n {sitesByGroup().map(({ group, sites }) => (\n <div key={group} className={s.column()}>\n <p id={`${id}-${group}`} className={s.title()}>\n {labels.groups[group]}\n </p>\n <ul aria-labelledby={`${id}-${group}`} className={s.list()}>\n {sites.map((item) => (\n <li key={item.id}>\n <a href={item.url} aria-current={item.id === current ? \"true\" : undefined} className={s.link()}>\n <span className={s.mark()}>\n <FamilyMark mark={item.mark} size={16} />\n </span>\n {item.name}\n {item.status !== \"released\" && <span className={s.tag()}>{labels.status[item.status]}</span>}\n {item.id === current && <span className=\"sr-only\">({labels.current})</span>}\n </a>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </nav>\n )}\n <div className={s.bottom()}>\n <a href={krizaka.url} className={s.signature()}>\n <KrizakaLogo size={18} animated={false} />\n {labels.signature[site.kind]}\n </a>\n {tag && (\n <span className={s.version()}>\n <span className=\"sr-only\">{labels.version} </span>\n {tag}\n </span>\n )}\n <span>{labels.place}</span>\n {legal && <div className={s.legal()}>{legal}</div>}\n </div>\n </div>\n </footer>\n );\n}\n\nexport type SiteFooterColumnProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n /** The column's heading (“Docs”) — passed translated. */\n title: string;\n /** Its links (`SiteFooter.Link`). */\n children: React.ReactNode;\n};\n\n/** One of the site's own columns: a heading and its links. */\nexport function SiteFooterColumn({ title, children, className, ...props }: SiteFooterColumnProps) {\n const id = React.useId();\n return (\n <div className={s.column({ className })} {...props}>\n <p id={id} className={s.title()}>\n {title}\n </p>\n <ul aria-labelledby={id} className={s.list()}>\n {React.Children.map(children, (child) => (child ? <li>{child}</li> : null))}\n </ul>\n </div>\n );\n}\n\nexport type SiteFooterLinkProps = React.ComponentProps<\"a\"> & {\n /** The current page: `aria-current=\"page\"`. */\n active?: boolean;\n /** Renders your router's `<Link>`. */\n asChild?: boolean;\n};\n\n/** A link of the footer. */\nexport function SiteFooterLink({ active, asChild, className, ...props }: SiteFooterLinkProps) {\n const Comp = asChild ? Slot.Root : \"a\";\n return <Comp aria-current={active ? \"page\" : undefined} className={s.link({ className })} {...props} />;\n}\n\nSiteFooter.Column = SiteFooterColumn;\nSiteFooter.Link = SiteFooterLink;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/site-footer/site-footer.tsx"],"sourcesContent":["// Client (the marks hold an id). The footer shared by every site of the Krizaka family: the site's own columns, then the\n// family in columns from `@krizaka/ui/sites` (the same groups as the bar's switcher), then the signature line — “A\n// Krizaka product” by the kind of the current site — the version and the place.\nimport { Slot } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { FamilyMark } from \"../family-mark\";\nimport { KrizakaLogo } from \"../marks/KrizakaLogo\";\nimport { type FamilyLabels, familyLabels, siteById, type SiteId, sitesByGroup } from \"../sites/sites\";\n\nexport const siteFooter = tv({\n slots: {\n root: \"w-full border-t border-border-subtle bg-surface-0 text-fg\",\n inner:\n \"mx-auto grid w-full max-w-[calc(var(--kz-page-max,72rem)_+_2*var(--kz-page-gutter,clamp(16px,3.2vw,32px)))] grid-cols-[minmax(0,1fr)] gap-10 px-[var(--kz-page-gutter,clamp(16px,3.2vw,32px))] py-12\",\n top: \"grid grid-cols-[minmax(0,1fr)] gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(0,2fr)]\",\n site: \"grid content-start gap-3\",\n siteName: \"inline-flex items-center gap-2 font-display text-[15px] font-bold tracking-tight text-fg\",\n siteText: \"max-w-xs text-sm leading-relaxed text-fg-secondary\",\n own: \"grid grid-cols-[repeat(auto-fit,minmax(9rem,1fr))] gap-8\",\n family: \"grid grid-cols-2 gap-8 border-t border-border-subtle pt-8 md:grid-cols-4\",\n column: \"grid min-w-0 content-start gap-3\",\n title: \"text-[11px] font-semibold uppercase tracking-wider text-fg-secondary\",\n list: \"grid min-w-0 gap-2\",\n link:\n \"inline-flex min-h-6 min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5 rounded-md text-sm [overflow-wrap:anywhere] text-fg-secondary no-underline transition-colors hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg aria-[current=true]:text-fg aria-[current=true]:font-semibold\",\n mark: \"flex h-4 w-4 shrink-0 items-center justify-center text-fg\",\n tag: \"rounded-full bg-surface-3 px-1.5 py-px text-[10px] font-semibold uppercase tracking-wider text-fg-secondary\",\n bottom: \"flex flex-wrap items-center gap-x-5 gap-y-3 border-t border-border-subtle pt-6 text-xs text-fg-secondary\",\n signature:\n \"inline-flex items-center gap-2 rounded-md font-medium text-fg no-underline hover:text-fg-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n version:\n \"rounded-full border border-border-subtle bg-surface-2 px-2 py-0.5 font-mono text-[11px] text-fg-secondary\",\n legal: \"flex flex-wrap items-center gap-x-4 gap-y-2 sm:ml-auto\",\n },\n variants: {\n // `site`: the full footer. `docs`: no site block, the columns in one row, on the documentation's width. `app`: one\n // slim line inside a signed-in product — signature, version, legal links.\n variant: {\n site: {},\n docs: {\n inner: \"max-w-[calc(var(--kz-page-max-docs,88rem)_+_2*var(--kz-page-gutter,clamp(16px,3.2vw,32px)))] gap-6 py-8\",\n top: \"lg:grid-cols-[minmax(0,1fr)]\",\n own: \"sm:grid-cols-4\",\n },\n app: {\n root: \"bg-transparent\",\n inner: \"gap-0 py-3\",\n bottom: \"border-t-0 pt-0\",\n },\n },\n },\n defaultVariants: { variant: \"site\" },\n});\n\nexport type SiteFooterProps = Omit<React.ComponentProps<\"footer\">, \"children\"> & {\n /** The site this footer belongs to (`@krizaka/ui/sites`): its mark and line, its signature, marked in the family. */\n current: SiteId;\n /**\n * The family's words, passed translated: `familyLabels.fr` from `@krizaka/ui/sites`, or your own of the same shape.\n * @default familyLabels.en\n */\n labels?: FamilyLabels;\n /** The site's own columns (`SiteFooter.Column`), before the family. */\n children?: React.ReactNode;\n /** The version the site runs (`1.2.3`, shown `v1.2.3`). */\n version?: string;\n /** The environment, when it is not production (`DEV`). */\n env?: string;\n /**\n * Shows the family in columns (the Krizaka sites: www, ui., java.). A product is independent once deployed: pass\n * `family={false}` and the footer holds only its own columns, the legal links, the version and one publisher line —\n * “A Krizaka product”, linking to www.krizaka.com.\n * @default true\n */\n family?: boolean;\n /** The end of the signature line: legal links, a language switch (`SiteFooter.Link`s or any inline content). */\n legal?: React.ReactNode;\n /**\n * `site` — the full footer of a marketing or company site. `docs` — a compact one for documentation pages (no site\n * block, the columns in a row, the documentation's width; never the family). `app` — one slim line inside a signed-in\n * product: the publisher line, the version and the legal links (no columns, no family); render it once, in the\n * layout, and not at all where the app shell has a sidebar that holds them.\n * @default \"site\"\n */\n variant?: \"site\" | \"docs\" | \"app\";\n};\n\n/** The footer of a Krizaka site: its own columns, the family in columns, the signature, the version, Montréal. */\nexport function SiteFooter({\n current,\n labels = familyLabels.en,\n children,\n version,\n env,\n legal,\n family: familyProp = true,\n variant = \"site\",\n className,\n ...props\n}: SiteFooterProps) {\n const id = React.useId();\n const s = siteFooter({ variant });\n const family = variant === \"site\" && familyProp;\n const slim = variant === \"app\";\n const site = siteById(current);\n const krizaka = siteById(\"krizaka\");\n const tag = [env, version && `v${version.replace(/^v/, \"\")}`].filter(Boolean).join(\" · \");\n return (\n <footer className={s.root({ className })} {...props}>\n <div className={s.inner()}>\n {!slim && (\n <div className={s.top()}>\n {variant === \"site\" && (\n <div className={s.site()}>\n <a href={site.url} className={s.siteName()}>\n <FamilyMark mark={site.mark} size={24} />\n {site.name}\n </a>\n <p className={s.siteText()}>{labels.descriptions[site.id]}</p>\n </div>\n )}\n {React.Children.toArray(children).length > 0 && <div className={s.own()}>{children}</div>}\n </div>\n )}\n {family && (\n <nav aria-label={labels.family} className={s.family()}>\n {sitesByGroup().map(({ group, sites }) => (\n <div key={group} className={s.column()}>\n <p id={`${id}-${group}`} className={s.title()}>\n {labels.groups[group]}\n </p>\n <ul aria-labelledby={`${id}-${group}`} className={s.list()}>\n {sites.map((item) => (\n <li key={item.id}>\n <a href={item.url} aria-current={item.id === current ? \"true\" : undefined} className={s.link()}>\n <span className={s.mark()}>\n <FamilyMark mark={item.mark} size={16} />\n </span>\n {item.name}\n {item.status !== \"released\" && <span className={s.tag()}>{labels.status[item.status]}</span>}\n {item.id === current && <span className=\"sr-only\">({labels.current})</span>}\n </a>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </nav>\n )}\n <div className={s.bottom()}>\n <a href={krizaka.url} className={s.signature()}>\n <KrizakaLogo size={18} animated={false} />\n {labels.signature[site.kind]}\n </a>\n {tag && (\n <span className={s.version()}>\n <span className=\"sr-only\">{labels.version} </span>\n {tag}\n </span>\n )}\n {!slim && <span>{labels.place}</span>}\n {legal && <div className={s.legal()}>{legal}</div>}\n </div>\n </div>\n </footer>\n );\n}\n\nexport type SiteFooterColumnProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n /** The column's heading (“Docs”) — passed translated. */\n title: string;\n /** Its links (`SiteFooter.Link`). */\n children: React.ReactNode;\n};\n\n/** One of the site's own columns: a heading and its links. */\nexport function SiteFooterColumn({ title, children, className, ...props }: SiteFooterColumnProps) {\n const id = React.useId();\n // A group with no link is not a column: only a heading over nothing.\n if (React.Children.toArray(children).length === 0) return null;\n const s = siteFooter();\n return (\n <div className={s.column({ className })} {...props}>\n <p id={id} className={s.title()}>\n {title}\n </p>\n <ul aria-labelledby={id} className={s.list()}>\n {React.Children.toArray(children).map((child, i) => <li key={i}>{child}</li>)}\n </ul>\n </div>\n );\n}\n\nexport type SiteFooterLinkProps = React.ComponentProps<\"a\"> & {\n /** The current page: `aria-current=\"page\"`. */\n active?: boolean;\n /** Renders your router's `<Link>`. */\n asChild?: boolean;\n};\n\n/** A link of the footer. */\nexport function SiteFooterLink({ active, asChild, className, ...props }: SiteFooterLinkProps) {\n const s = siteFooter();\n const Comp = asChild ? Slot.Root : \"a\";\n return <Comp aria-current={active ? \"page\" : undefined} className={s.link({ className })} {...props} />;\n}\n\nSiteFooter.Column = SiteFooterColumn;\nSiteFooter.Link = SiteFooterLink;\n"],"mappings":"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","names":[]}
|
package/dist/slider.js
CHANGED
package/dist/stage-banner.js
CHANGED
package/dist/step-showcase.js
CHANGED
package/dist/tabs.js
CHANGED
|
@@ -15,7 +15,7 @@ var tabs = tv({
|
|
|
15
15
|
// (server render), each trigger carries its own active style.
|
|
16
16
|
list: "group/tabs relative isolate flex shrink-0 data-[orientation=vertical]:flex-col before:pointer-events-none before:absolute before:-z-10 before:opacity-0 before:transition-[translate,width,height,opacity] before:duration-300 motion-reduce:before:transition-none data-[indicator=on]:before:opacity-100",
|
|
17
17
|
trigger: "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40",
|
|
18
|
-
content: "kz-fade min-w-0 flex-1 rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
|
|
18
|
+
content: "kz-fade min-w-0 flex-1 rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring data-[state=inactive]:hidden"
|
|
19
19
|
},
|
|
20
20
|
variants: {
|
|
21
21
|
variant: {
|
package/dist/tabs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tabs/tabs.tsx"],"sourcesContent":["// Client (a context). Radix Tabs does the roles (tablist, tab, tabpanel), the aria-selected / aria-controls wiring,\n// the roving focus (arrows, Home, End) and automatic activation: this file only holds the three looks.\nimport { Tabs as TabsPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { useSlidingIndicator } from \"../sliding-indicator\";\n\nexport const tabs = tv({\n slots: {\n root: \"flex gap-4 data-[orientation=horizontal]:flex-col data-[orientation=vertical]:flex-row\",\n // One light glides from the active tab to the next (`before:`, placed by useSlidingIndicator); until it is placed\n // (server render), each trigger carries its own active style.\n list:\n \"group/tabs relative isolate flex shrink-0 data-[orientation=vertical]:flex-col \" +\n \"before:pointer-events-none before:absolute before:-z-10 before:opacity-0 before:transition-[translate,width,height,opacity] before:duration-300 \" +\n \"motion-reduce:before:transition-none data-[indicator=on]:before:opacity-100\",\n trigger:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-colors \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40\",\n content: \"kz-fade min-w-0 flex-1 rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n },\n variants: {\n variant: {\n /* The section of a page: a line under the list, the active tab underlined in the accent. */\n underline: {\n list:\n \"gap-1 border-border-default data-[orientation=horizontal]:border-b data-[orientation=vertical]:border-r before:rounded-full before:bg-accent \" +\n \"data-[orientation=horizontal]:before:-bottom-px data-[orientation=horizontal]:before:left-0 data-[orientation=horizontal]:before:h-0.5 \" +\n \"data-[orientation=horizontal]:before:w-(--kz-ind-w) data-[orientation=horizontal]:before:translate-x-(--kz-ind-x) \" +\n \"data-[orientation=vertical]:before:-right-px data-[orientation=vertical]:before:top-0 data-[orientation=vertical]:before:w-0.5 \" +\n \"data-[orientation=vertical]:before:h-(--kz-ind-h) data-[orientation=vertical]:before:translate-y-(--kz-ind-y)\",\n trigger:\n \"relative rounded-md px-3 py-2.5 text-sm text-fg-secondary hover:text-fg data-[state=active]:text-fg \" +\n \"after:absolute after:rounded-full after:bg-transparent data-[state=active]:after:bg-accent \" +\n \"data-[orientation=horizontal]:after:inset-x-2 data-[orientation=horizontal]:after:-bottom-px data-[orientation=horizontal]:after:h-0.5 \" +\n \"data-[orientation=vertical]:justify-start data-[orientation=vertical]:after:inset-y-1.5 data-[orientation=vertical]:after:-right-px data-[orientation=vertical]:after:w-0.5 \" +\n \"group-data-[indicator=on]/tabs:data-[state=active]:after:bg-transparent\",\n },\n /* A view switch: equal segments in a track, the active one filled. */\n segmented: {\n list:\n \"inline-grid auto-cols-fr grid-flow-col gap-1 self-start rounded-xl border border-border-default bg-surface-1 p-1 data-[orientation=vertical]:grid-flow-row \" +\n \"before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) before:rounded-lg before:bg-accent before:shadow-sm\",\n trigger:\n \"min-h-8 rounded-lg px-3 py-1.5 text-xs text-fg-secondary hover:bg-surface-2 hover:text-fg \" +\n \"data-[state=active]:bg-accent data-[state=active]:text-on-accent data-[state=active]:shadow-sm data-[state=active]:hover:bg-accent \" +\n \"transition-colors group-data-[indicator=on]/tabs:data-[state=active]:bg-transparent group-data-[indicator=on]/tabs:data-[state=active]:shadow-none\",\n },\n /* Pills that scroll sideways on a phone: a feed's sections. */\n pills: {\n list:\n \"gap-1.5 overflow-x-auto overflow-y-hidden overscroll-x-contain pt-1 -mt-1 pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden \" +\n \"before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) \" +\n \"before:rounded-full before:border before:border-accent before:bg-accent-soft\",\n trigger:\n \"h-9 rounded-full border border-border-default bg-surface-1 px-4 text-xs text-fg-secondary hover:border-border-strong hover:text-fg \" +\n \"data-[state=active]:border-accent data-[state=active]:bg-accent-soft data-[state=active]:text-fg \" +\n \"group-data-[indicator=on]/tabs:data-[state=active]:border-transparent group-data-[indicator=on]/tabs:data-[state=active]:bg-transparent\",\n },\n },\n },\n defaultVariants: { variant: \"underline\" },\n});\n\nexport type TabsVariants = VariantProps<typeof tabs>;\ntype Variant = NonNullable<TabsVariants[\"variant\"]>;\n\nconst VariantContext = React.createContext<Variant>(\"underline\");\n\nexport type TabsRootProps = React.ComponentProps<typeof TabsPrimitive.Root> & {\n /** underline (the sections of a page) · segmented (a view switch) · pills (a feed's sections). */\n variant?: TabsVariants[\"variant\"];\n};\n\n/** `value`/`defaultValue` + `onValueChange`, `orientation` (horizontal by default), `variant` for the list. */\nexport function TabsRoot({ variant = \"underline\", className, ...props }: TabsRootProps) {\n return (\n <VariantContext.Provider value={variant}>\n <TabsPrimitive.Root data-variant={variant} className={tabs({ variant }).root({ className })} {...props} />\n </VariantContext.Provider>\n );\n}\n\n/** The tabs. Name it (`aria-label`) when no heading says what it switches. One light glides to the active tab. */\nexport function TabsList({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.List>) {\n const variant = React.useContext(VariantContext);\n const { ref } = useSlidingIndicator<HTMLDivElement>({ item: \"[role=tab]\", active: \"[role=tab][data-state=active]\" });\n return <TabsPrimitive.List ref={ref} data-variant={variant} className={tabs({ variant }).list({ className })} {...props} />;\n}\n\nexport function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n const variant = React.useContext(VariantContext);\n return <TabsPrimitive.Trigger className={tabs({ variant }).trigger({ className })} {...props} />;\n}\n\nexport function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return <TabsPrimitive.Content className={tabs().content({ className })} {...props} />;\n}\n\n/** `Tabs.Root/List/Trigger/Content` — `variant` underline · segmented · pills on the root. */\nexport const Tabs = { Root: TabsRoot, List: TabsList, Trigger: TabsTrigger, Content: TabsContent };\n"],"mappings":";;;;;;AAEA,SAAS,QAAQ,qBAAqB;AACtC,YAAY,WAAW;AACvB,SAAS,UAA6B;AA2EhC;AAvEC,IAAM,OAAO,GAAG;AAAA,EACrB,OAAO;AAAA,IACL,MAAM;AAAA;AAAA;AAAA,IAGN,MACE;AAAA,IAGF,SACE;AAAA,IAEF,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA;AAAA,MAEP,WAAW;AAAA,QACT,MACE;AAAA,QAKF,SACE;AAAA,MAKJ;AAAA;AAAA,MAEA,WAAW;AAAA,QACT,MACE;AAAA,QAEF,SACE;AAAA,MAGJ;AAAA;AAAA,MAEA,OAAO;AAAA,QACL,MACE;AAAA,QAGF,SACE;AAAA,MAGJ;AAAA,IACF;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,SAAS,YAAY;AAC1C,CAAC;AAKD,IAAM,iBAAuB,oBAAuB,WAAW;AAQxD,SAAS,SAAS,EAAE,UAAU,aAAa,WAAW,GAAG,MAAM,GAAkB;AACtF,SACE,oBAAC,eAAe,UAAf,EAAwB,OAAO,SAC9B,8BAAC,cAAc,MAAd,EAAmB,gBAAc,SAAS,WAAW,KAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO,GAC1G;AAEJ;AAGO,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAoD;AACjG,QAAM,UAAgB,iBAAW,cAAc;AAC/C,QAAM,EAAE,IAAI,IAAI,oBAAoC,EAAE,MAAM,cAAc,QAAQ,gCAAgC,CAAC;AACnH,SAAO,oBAAC,cAAc,MAAd,EAAmB,KAAU,gBAAc,SAAS,WAAW,KAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAC3H;AAEO,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAuD;AACvG,QAAM,UAAgB,iBAAW,cAAc;AAC/C,SAAO,oBAAC,cAAc,SAAd,EAAsB,WAAW,KAAK,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAChG;AAEO,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAuD;AACvG,SAAO,oBAAC,cAAc,SAAd,EAAsB,WAAW,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACrF;AAGO,IAAM,OAAO,EAAE,MAAM,UAAU,MAAM,UAAU,SAAS,aAAa,SAAS,YAAY;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/tabs/tabs.tsx"],"sourcesContent":["// Client (a context). Radix Tabs does the roles (tablist, tab, tabpanel), the aria-selected / aria-controls wiring,\n// the roving focus (arrows, Home, End) and automatic activation: this file only holds the three looks.\nimport { Tabs as TabsPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { useSlidingIndicator } from \"../sliding-indicator\";\n\nexport const tabs = tv({\n slots: {\n root: \"flex gap-4 data-[orientation=horizontal]:flex-col data-[orientation=vertical]:flex-row\",\n // One light glides from the active tab to the next (`before:`, placed by useSlidingIndicator); until it is placed\n // (server render), each trigger carries its own active style.\n list:\n \"group/tabs relative isolate flex shrink-0 data-[orientation=vertical]:flex-col \" +\n \"before:pointer-events-none before:absolute before:-z-10 before:opacity-0 before:transition-[translate,width,height,opacity] before:duration-300 \" +\n \"motion-reduce:before:transition-none data-[indicator=on]:before:opacity-100\",\n trigger:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-colors \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40\",\n content: \"kz-fade min-w-0 flex-1 rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring data-[state=inactive]:hidden\",\n },\n variants: {\n variant: {\n /* The section of a page: a line under the list, the active tab underlined in the accent. */\n underline: {\n list:\n \"gap-1 border-border-default data-[orientation=horizontal]:border-b data-[orientation=vertical]:border-r before:rounded-full before:bg-accent \" +\n \"data-[orientation=horizontal]:before:-bottom-px data-[orientation=horizontal]:before:left-0 data-[orientation=horizontal]:before:h-0.5 \" +\n \"data-[orientation=horizontal]:before:w-(--kz-ind-w) data-[orientation=horizontal]:before:translate-x-(--kz-ind-x) \" +\n \"data-[orientation=vertical]:before:-right-px data-[orientation=vertical]:before:top-0 data-[orientation=vertical]:before:w-0.5 \" +\n \"data-[orientation=vertical]:before:h-(--kz-ind-h) data-[orientation=vertical]:before:translate-y-(--kz-ind-y)\",\n trigger:\n \"relative rounded-md px-3 py-2.5 text-sm text-fg-secondary hover:text-fg data-[state=active]:text-fg \" +\n \"after:absolute after:rounded-full after:bg-transparent data-[state=active]:after:bg-accent \" +\n \"data-[orientation=horizontal]:after:inset-x-2 data-[orientation=horizontal]:after:-bottom-px data-[orientation=horizontal]:after:h-0.5 \" +\n \"data-[orientation=vertical]:justify-start data-[orientation=vertical]:after:inset-y-1.5 data-[orientation=vertical]:after:-right-px data-[orientation=vertical]:after:w-0.5 \" +\n \"group-data-[indicator=on]/tabs:data-[state=active]:after:bg-transparent\",\n },\n /* A view switch: equal segments in a track, the active one filled. */\n segmented: {\n list:\n \"inline-grid auto-cols-fr grid-flow-col gap-1 self-start rounded-xl border border-border-default bg-surface-1 p-1 data-[orientation=vertical]:grid-flow-row \" +\n \"before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) before:rounded-lg before:bg-accent before:shadow-sm\",\n trigger:\n \"min-h-8 rounded-lg px-3 py-1.5 text-xs text-fg-secondary hover:bg-surface-2 hover:text-fg \" +\n \"data-[state=active]:bg-accent data-[state=active]:text-on-accent data-[state=active]:shadow-sm data-[state=active]:hover:bg-accent \" +\n \"transition-colors group-data-[indicator=on]/tabs:data-[state=active]:bg-transparent group-data-[indicator=on]/tabs:data-[state=active]:shadow-none\",\n },\n /* Pills that scroll sideways on a phone: a feed's sections. */\n pills: {\n list:\n \"gap-1.5 overflow-x-auto overflow-y-hidden overscroll-x-contain pt-1 -mt-1 pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden \" +\n \"before:left-0 before:top-0 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) \" +\n \"before:rounded-full before:border before:border-accent before:bg-accent-soft\",\n trigger:\n \"h-9 rounded-full border border-border-default bg-surface-1 px-4 text-xs text-fg-secondary hover:border-border-strong hover:text-fg \" +\n \"data-[state=active]:border-accent data-[state=active]:bg-accent-soft data-[state=active]:text-fg \" +\n \"group-data-[indicator=on]/tabs:data-[state=active]:border-transparent group-data-[indicator=on]/tabs:data-[state=active]:bg-transparent\",\n },\n },\n },\n defaultVariants: { variant: \"underline\" },\n});\n\nexport type TabsVariants = VariantProps<typeof tabs>;\ntype Variant = NonNullable<TabsVariants[\"variant\"]>;\n\nconst VariantContext = React.createContext<Variant>(\"underline\");\n\nexport type TabsRootProps = React.ComponentProps<typeof TabsPrimitive.Root> & {\n /** underline (the sections of a page) · segmented (a view switch) · pills (a feed's sections). */\n variant?: TabsVariants[\"variant\"];\n};\n\n/** `value`/`defaultValue` + `onValueChange`, `orientation` (horizontal by default), `variant` for the list. */\nexport function TabsRoot({ variant = \"underline\", className, ...props }: TabsRootProps) {\n return (\n <VariantContext.Provider value={variant}>\n <TabsPrimitive.Root data-variant={variant} className={tabs({ variant }).root({ className })} {...props} />\n </VariantContext.Provider>\n );\n}\n\n/** The tabs. Name it (`aria-label`) when no heading says what it switches. One light glides to the active tab. */\nexport function TabsList({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.List>) {\n const variant = React.useContext(VariantContext);\n const { ref } = useSlidingIndicator<HTMLDivElement>({ item: \"[role=tab]\", active: \"[role=tab][data-state=active]\" });\n return <TabsPrimitive.List ref={ref} data-variant={variant} className={tabs({ variant }).list({ className })} {...props} />;\n}\n\nexport function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n const variant = React.useContext(VariantContext);\n return <TabsPrimitive.Trigger className={tabs({ variant }).trigger({ className })} {...props} />;\n}\n\nexport function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return <TabsPrimitive.Content className={tabs().content({ className })} {...props} />;\n}\n\n/** `Tabs.Root/List/Trigger/Content` — `variant` underline · segmented · pills on the root. */\nexport const Tabs = { Root: TabsRoot, List: TabsList, Trigger: TabsTrigger, Content: TabsContent };\n"],"mappings":";;;;;;AAEA,SAAS,QAAQ,qBAAqB;AACtC,YAAY,WAAW;AACvB,SAAS,UAA6B;AA2EhC;AAvEC,IAAM,OAAO,GAAG;AAAA,EACrB,OAAO;AAAA,IACL,MAAM;AAAA;AAAA;AAAA,IAGN,MACE;AAAA,IAGF,SACE;AAAA,IAEF,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA;AAAA,MAEP,WAAW;AAAA,QACT,MACE;AAAA,QAKF,SACE;AAAA,MAKJ;AAAA;AAAA,MAEA,WAAW;AAAA,QACT,MACE;AAAA,QAEF,SACE;AAAA,MAGJ;AAAA;AAAA,MAEA,OAAO;AAAA,QACL,MACE;AAAA,QAGF,SACE;AAAA,MAGJ;AAAA,IACF;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,SAAS,YAAY;AAC1C,CAAC;AAKD,IAAM,iBAAuB,oBAAuB,WAAW;AAQxD,SAAS,SAAS,EAAE,UAAU,aAAa,WAAW,GAAG,MAAM,GAAkB;AACtF,SACE,oBAAC,eAAe,UAAf,EAAwB,OAAO,SAC9B,8BAAC,cAAc,MAAd,EAAmB,gBAAc,SAAS,WAAW,KAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO,GAC1G;AAEJ;AAGO,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAoD;AACjG,QAAM,UAAgB,iBAAW,cAAc;AAC/C,QAAM,EAAE,IAAI,IAAI,oBAAoC,EAAE,MAAM,cAAc,QAAQ,gCAAgC,CAAC;AACnH,SAAO,oBAAC,cAAc,MAAd,EAAmB,KAAU,gBAAc,SAAS,WAAW,KAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAC3H;AAEO,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAuD;AACvG,QAAM,UAAgB,iBAAW,cAAc;AAC/C,SAAO,oBAAC,cAAc,SAAd,EAAsB,WAAW,KAAK,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAChG;AAEO,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAuD;AACvG,SAAO,oBAAC,cAAc,SAAd,EAAsB,WAAW,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACrF;AAGO,IAAM,OAAO,EAAE,MAAM,UAAU,MAAM,UAAU,SAAS,aAAa,SAAS,YAAY;","names":[]}
|
package/dist/terminal-replay.js
CHANGED
package/dist/theme.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
buttonVariants
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CHOJUCVE.js";
|
|
5
5
|
import "./chunk-D3T54RSL.js";
|
|
6
6
|
import "./chunk-WEVYKZIF.js";
|
|
7
|
+
import "./chunk-NSLXEDIS.js";
|
|
7
8
|
|
|
8
9
|
// src/theme/theme.tsx
|
|
9
10
|
import * as React from "react";
|
package/dist/theme.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/theme/theme.tsx"],"sourcesContent":["// Client. ONE mechanism for the whole organisation: dark by default, `html.light` for light, `html.theme-<name>` for a\n// named theme, persisted in localStorage (`kz-theme` for the mode, `kz-theme-name` for the named theme).\nimport * as React from \"react\";\n\nimport { type ButtonVariants, buttonVariants } from \"../button/button\";\n\nexport type Mode = \"dark\" | \"light\" | \"system\";\n\nconst MODE_KEY = \"kz-theme\";\nconst NAME_KEY = \"kz-theme-name\";\nconst MODES: readonly Mode[] = [\"dark\", \"light\", \"system\"];\nconst DARK_QUERY = \"(prefers-color-scheme: dark)\";\n\nconst isMode = (value: unknown): value is Mode => MODES.includes(value as Mode);\n\n// Storage blocked (private mode, sandbox): the choice lives in memory for the page.\nconst memory = new Map<string, string>();\n\nfunction read(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return memory.get(key) ?? null;\n }\n}\n\nfunction write(key: string, value: string | null) {\n if (value === null) memory.delete(key);\n else memory.set(key, value);\n try {\n if (value === null) localStorage.removeItem(key);\n else localStorage.setItem(key, value);\n } catch {\n // storage blocked: memory holds it\n }\n}\n\n// The persisted choice is an external store: every provider and tab reads the same value, the server reads none.\nconst listeners = new Set<() => void>();\nconst notify = () => listeners.forEach((listener) => listener());\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n window.addEventListener(\"storage\", listener);\n return () => {\n listeners.delete(listener);\n window.removeEventListener(\"storage\", listener);\n };\n}\n\nfunction applyMode(mode: Mode) {\n const dark = window.matchMedia(DARK_QUERY).matches;\n document.documentElement.classList.toggle(\"light\", mode === \"light\" || (mode === \"system\" && !dark));\n}\n\nfunction applyName(previous: string | null, next: string | null) {\n const classes = document.documentElement.classList;\n if (previous) classes.remove(`theme-${previous}`);\n if (next) classes.add(`theme-${next}`);\n}\n\nexport type ThemeScriptProps = {\n /** The nonce of a strict Content-Security-Policy (`script-src 'nonce-…'`). */\n nonce?: string;\n /**\n * The mode before the visitor chooses one — pass the same value as `ThemeProvider`'s `defaultMode`. A persisted\n * choice (`kz-theme`) always wins.\n * @default \"system\"\n */\n defaultMode?: Mode;\n};\n\n/**\n * In <head>, before anything renders: applies the persisted mode (else `defaultMode`) and named theme, so the page\n * never flashes. `nonce` for a strict Content-Security-Policy.\n */\nexport function ThemeScript({ nonce, defaultMode = \"system\" }: ThemeScriptProps) {\n const fallback = isMode(defaultMode) ? defaultMode : \"system\";\n const js =\n `(function(){try{var m=localStorage.getItem(\"${MODE_KEY}\");if(m!==\"dark\"&&m!==\"light\"&&m!==\"system\")m=\"${fallback}\";` +\n `var n=localStorage.getItem(\"${NAME_KEY}\");var d=matchMedia(\"${DARK_QUERY}\").matches;var c=document.documentElement.classList;` +\n `c.toggle(\"light\",m===\"light\"||(m===\"system\"&&!d));if(n)c.add(\"theme-\"+n)}catch(e){}})()`;\n return <script nonce={nonce} dangerouslySetInnerHTML={{ __html: js }} />;\n}\n\nexport type ThemeContextValue = {\n /** The chosen mode: dark, light or follow the system. */\n mode: Mode;\n setMode: (mode: Mode) => void;\n /** The named theme (`html.theme-<name>`), or null. */\n theme: string | null;\n setTheme: (theme: string | null) => void;\n};\n\nconst ThemeContext = React.createContext<ThemeContextValue | null>(null);\n\nexport type ThemeProviderProps = {\n children: React.ReactNode;\n /**\n * The mode before the visitor chooses one (nothing persisted as `kz-theme`) — pass the same value to `ThemeScript`.\n * @default \"system\"\n */\n defaultMode?: Mode;\n};\n\nexport function ThemeProvider({ children, defaultMode = \"system\" }: ThemeProviderProps) {\n // Before hydration the server knows nothing persisted (ThemeScript has already applied it to <html>).\n const stored = React.useSyncExternalStore(subscribe, () => read(MODE_KEY), () => null);\n const mode: Mode = isMode(stored) ? stored : defaultMode;\n const theme = React.useSyncExternalStore(subscribe, () => read(NAME_KEY), () => null);\n\n // The same resolution as ThemeScript (a no-op after it), for an app that renders the provider without the script.\n React.useEffect(() => {\n const persisted = read(MODE_KEY);\n applyMode(isMode(persisted) ? persisted : defaultMode);\n }, [defaultMode]);\n\n // \"system\" follows the operating system while the page is open.\n React.useEffect(() => {\n if (mode !== \"system\") return;\n const query = window.matchMedia(DARK_QUERY);\n const onChange = () => applyMode(\"system\");\n query.addEventListener?.(\"change\", onChange);\n return () => query.removeEventListener?.(\"change\", onChange);\n }, [mode]);\n\n const setMode = React.useCallback((next: Mode) => {\n write(MODE_KEY, next);\n applyMode(next);\n notify();\n }, []);\n\n const setTheme = React.useCallback((next: string | null) => {\n applyName(read(NAME_KEY), next);\n write(NAME_KEY, next);\n notify();\n }, []);\n\n const value = React.useMemo(() => ({ mode, setMode, theme, setTheme }), [mode, setMode, theme, setTheme]);\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\nexport function useTheme(): ThemeContextValue {\n const context = React.useContext(ThemeContext);\n if (!context) throw new Error(\"useTheme: wrap the app in <ThemeProvider>\");\n return context;\n}\n\nconst ICONS: Record<Mode, React.ReactNode> = {\n dark: <path d=\"M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5Z\" />,\n light: (\n <>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4\" />\n </>\n ),\n system: (\n <>\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"12\" rx=\"2\" />\n <path d=\"M8 20h8M12 16v4\" />\n </>\n ),\n};\n\nexport type ThemeToggleProps = Omit<React.ComponentProps<\"button\">, \"onClick\" | \"children\"> &\n Pick<ButtonVariants, \"variant\" | \"shape\"> & {\n /** Any `Button` variant. */\n variant?: ButtonVariants[\"variant\"];\n /**\n * rounded · pill.\n * @default \"rounded\"\n */\n shape?: ButtonVariants[\"shape\"];\n /** The accessible name — a string, or one per current mode (e.g. `(mode) => t(\"theme.\" + mode)`). */\n label: string | ((mode: Mode) => string);\n };\n\n/**\n * An icon button (styled as `IconButton`, without its Slot) that cycles dark → light → system. Needs a\n * <ThemeProvider> above it. State: `data-mode`.\n */\nexport function ThemeToggle({ label, variant = \"ghost\", shape, className, ...props }: ThemeToggleProps) {\n const { mode, setMode } = useTheme();\n const next = MODES[(MODES.indexOf(mode) + 1) % MODES.length] as Mode;\n const name = typeof label === \"function\" ? label(mode) : label;\n return (\n <button\n type=\"button\"\n aria-label={name}\n title={name}\n data-mode={mode}\n onClick={() => setMode(next)}\n className={buttonVariants({ variant, shape, size: \"icon\", className })}\n {...props}\n >\n <svg viewBox=\"0 0 24 24\" className=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n {ICONS[mode]}\n </svg>\n </button>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/theme/theme.tsx"],"sourcesContent":["// Client. ONE mechanism for the whole organisation: dark by default, `html.light` for light, `html.theme-<name>` for a\n// named theme, persisted in localStorage (`kz-theme` for the mode, `kz-theme-name` for the named theme).\nimport * as React from \"react\";\n\nimport { type ButtonVariants, buttonVariants } from \"../button/button\";\n\nexport type Mode = \"dark\" | \"light\" | \"system\";\n\nconst MODE_KEY = \"kz-theme\";\nconst NAME_KEY = \"kz-theme-name\";\nconst MODES: readonly Mode[] = [\"dark\", \"light\", \"system\"];\nconst DARK_QUERY = \"(prefers-color-scheme: dark)\";\n\nconst isMode = (value: unknown): value is Mode => MODES.includes(value as Mode);\n\n// Storage blocked (private mode, sandbox): the choice lives in memory for the page.\nconst memory = new Map<string, string>();\n\nfunction read(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return memory.get(key) ?? null;\n }\n}\n\nfunction write(key: string, value: string | null) {\n if (value === null) memory.delete(key);\n else memory.set(key, value);\n try {\n if (value === null) localStorage.removeItem(key);\n else localStorage.setItem(key, value);\n } catch {\n // storage blocked: memory holds it\n }\n}\n\n// The persisted choice is an external store: every provider and tab reads the same value, the server reads none.\nconst listeners = new Set<() => void>();\nconst notify = () => listeners.forEach((listener) => listener());\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n window.addEventListener(\"storage\", listener);\n return () => {\n listeners.delete(listener);\n window.removeEventListener(\"storage\", listener);\n };\n}\n\nfunction applyMode(mode: Mode) {\n const dark = window.matchMedia(DARK_QUERY).matches;\n document.documentElement.classList.toggle(\"light\", mode === \"light\" || (mode === \"system\" && !dark));\n}\n\nfunction applyName(previous: string | null, next: string | null) {\n const classes = document.documentElement.classList;\n if (previous) classes.remove(`theme-${previous}`);\n if (next) classes.add(`theme-${next}`);\n}\n\nexport type ThemeScriptProps = {\n /** The nonce of a strict Content-Security-Policy (`script-src 'nonce-…'`). */\n nonce?: string;\n /**\n * The mode before the visitor chooses one — pass the same value as `ThemeProvider`'s `defaultMode`. A persisted\n * choice (`kz-theme`) always wins.\n * @default \"system\"\n */\n defaultMode?: Mode;\n};\n\n/**\n * In <head>, before anything renders: applies the persisted mode (else `defaultMode`) and named theme, so the page\n * never flashes. `nonce` for a strict Content-Security-Policy.\n */\nexport function ThemeScript({ nonce, defaultMode = \"system\" }: ThemeScriptProps) {\n const fallback = isMode(defaultMode) ? defaultMode : \"system\";\n const js =\n `(function(){try{var m=localStorage.getItem(\"${MODE_KEY}\");if(m!==\"dark\"&&m!==\"light\"&&m!==\"system\")m=\"${fallback}\";` +\n `var n=localStorage.getItem(\"${NAME_KEY}\");var d=matchMedia(\"${DARK_QUERY}\").matches;var c=document.documentElement.classList;` +\n `c.toggle(\"light\",m===\"light\"||(m===\"system\"&&!d));if(n)c.add(\"theme-\"+n)}catch(e){}})()`;\n return <script nonce={nonce} dangerouslySetInnerHTML={{ __html: js }} />;\n}\n\nexport type ThemeContextValue = {\n /** The chosen mode: dark, light or follow the system. */\n mode: Mode;\n setMode: (mode: Mode) => void;\n /** The named theme (`html.theme-<name>`), or null. */\n theme: string | null;\n setTheme: (theme: string | null) => void;\n};\n\nconst ThemeContext = React.createContext<ThemeContextValue | null>(null);\n\nexport type ThemeProviderProps = {\n children: React.ReactNode;\n /**\n * The mode before the visitor chooses one (nothing persisted as `kz-theme`) — pass the same value to `ThemeScript`.\n * @default \"system\"\n */\n defaultMode?: Mode;\n};\n\nexport function ThemeProvider({ children, defaultMode = \"system\" }: ThemeProviderProps) {\n // Before hydration the server knows nothing persisted (ThemeScript has already applied it to <html>).\n const stored = React.useSyncExternalStore(subscribe, () => read(MODE_KEY), () => null);\n const mode: Mode = isMode(stored) ? stored : defaultMode;\n const theme = React.useSyncExternalStore(subscribe, () => read(NAME_KEY), () => null);\n\n // The same resolution as ThemeScript (a no-op after it), for an app that renders the provider without the script.\n React.useEffect(() => {\n const persisted = read(MODE_KEY);\n applyMode(isMode(persisted) ? persisted : defaultMode);\n }, [defaultMode]);\n\n // \"system\" follows the operating system while the page is open.\n React.useEffect(() => {\n if (mode !== \"system\") return;\n const query = window.matchMedia(DARK_QUERY);\n const onChange = () => applyMode(\"system\");\n query.addEventListener?.(\"change\", onChange);\n return () => query.removeEventListener?.(\"change\", onChange);\n }, [mode]);\n\n const setMode = React.useCallback((next: Mode) => {\n write(MODE_KEY, next);\n applyMode(next);\n notify();\n }, []);\n\n const setTheme = React.useCallback((next: string | null) => {\n applyName(read(NAME_KEY), next);\n write(NAME_KEY, next);\n notify();\n }, []);\n\n const value = React.useMemo(() => ({ mode, setMode, theme, setTheme }), [mode, setMode, theme, setTheme]);\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\nexport function useTheme(): ThemeContextValue {\n const context = React.useContext(ThemeContext);\n if (!context) throw new Error(\"useTheme: wrap the app in <ThemeProvider>\");\n return context;\n}\n\nconst ICONS: Record<Mode, React.ReactNode> = {\n dark: <path d=\"M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5Z\" />,\n light: (\n <>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4\" />\n </>\n ),\n system: (\n <>\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"12\" rx=\"2\" />\n <path d=\"M8 20h8M12 16v4\" />\n </>\n ),\n};\n\nexport type ThemeToggleProps = Omit<React.ComponentProps<\"button\">, \"onClick\" | \"children\"> &\n Pick<ButtonVariants, \"variant\" | \"shape\"> & {\n /** Any `Button` variant. */\n variant?: ButtonVariants[\"variant\"];\n /**\n * rounded · pill.\n * @default \"rounded\"\n */\n shape?: ButtonVariants[\"shape\"];\n /** The accessible name — a string, or one per current mode (e.g. `(mode) => t(\"theme.\" + mode)`). */\n label: string | ((mode: Mode) => string);\n };\n\n/**\n * An icon button (styled as `IconButton`, without its Slot) that cycles dark → light → system. Needs a\n * <ThemeProvider> above it. State: `data-mode`.\n */\nexport function ThemeToggle({ label, variant = \"ghost\", shape, className, ...props }: ThemeToggleProps) {\n const { mode, setMode } = useTheme();\n const next = MODES[(MODES.indexOf(mode) + 1) % MODES.length] as Mode;\n const name = typeof label === \"function\" ? label(mode) : label;\n return (\n <button\n type=\"button\"\n aria-label={name}\n title={name}\n data-mode={mode}\n onClick={() => setMode(next)}\n className={buttonVariants({ variant, shape, size: \"icon\", className })}\n {...props}\n >\n <svg viewBox=\"0 0 24 24\" className=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n {ICONS[mode]}\n </svg>\n </button>\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/toast.js
CHANGED
package/dist/toc.js
CHANGED
package/dist/tooltip.js
CHANGED
package/dist/update-prompt.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import "./chunk-TDG7ED2W.js";
|
|
2
2
|
import {
|
|
3
3
|
Button
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6ZYRUOTA.js";
|
|
5
5
|
import "./chunk-43PTCDTL.js";
|
|
6
6
|
import "./chunk-2VNYHG4E.js";
|
|
7
|
+
import "./chunk-W675RFOA.js";
|
|
7
8
|
|
|
8
9
|
// src/update-prompt/update-prompt.tsx
|
|
9
10
|
import { tv } from "tailwind-variants";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/update-prompt/update-prompt.tsx"],"sourcesContent":["// Server-safe. The soft invitation to update: a dismissible banner, in the flow of the page, never a blocker.\n// Every word is a prop (the app passes them translated); the version and the store URL come from `useAppConfig`.\nimport { Button } from \"@krizaka/ui/button\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const updatePrompt = tv({\n slots: {\n root: \"flex w-full flex-wrap items-center gap-3 rounded-xl border border-border-default bg-surface-1 p-4 text-sm text-fg\",\n mark: \"flex h-10 w-10 shrink-0 items-center justify-center [&>svg]:h-10 [&>svg]:w-10\",\n content: \"flex min-w-0 flex-1 flex-col gap-0.5\",\n title: \"font-semibold text-fg\",\n message: \"text-fg-secondary\",\n version: \"font-mono text-xs text-fg-tertiary\",\n actions: \"flex shrink-0 items-center gap-2\",\n },\n});\n\nexport type UpdatePromptProps = Omit<React.ComponentProps<\"section\">, \"title\"> & {\n /** The headline (“A new version is available”). */\n title: React.ReactNode;\n /** Why update, in a sentence — the backend's localized `message`. */\n message?: React.ReactNode;\n /** The versions, in words and mono (“1.2.0 → 1.4.0”). */\n versionLabel?: React.ReactNode;\n /** The product's mark (decorative), e.g. `<OrazakaLogo />`. */\n mark?: React.ReactNode;\n /** The button that updates (“Update”). */\n updateLabel: string;\n /** Opens the store page, or reloads the app on the new version. */\n onUpdate: () => void;\n /** The way out (“Later”). */\n laterLabel: string;\n /** Called by the way out: the hook remembers it for this version. */\n onLater: () => void;\n};\n\n/** The soft update: an invitation that can be dismissed, announced politely. */\nexport function UpdatePrompt({ title, message, versionLabel, mark, updateLabel, onUpdate, laterLabel, onLater, className, ...props }: UpdatePromptProps) {\n const s = updatePrompt();\n return (\n <section role=\"region\" aria-label={typeof title === \"string\" ? title : undefined} data-kind=\"update-soft\" className={s.root({ className })} {...props}>\n {mark && (\n <div aria-hidden className={s.mark()}>\n {mark}\n </div>\n )}\n <div className={s.content()}>\n <p className={s.title()}>{title}</p>\n {message && <p className={s.message()}>{message}</p>}\n {versionLabel && <p className={s.version()}>{versionLabel}</p>}\n </div>\n <div className={s.actions()}>\n <Button variant=\"ghost\" size=\"sm\" onClick={onLater}>\n {laterLabel}\n </Button>\n <Button variant=\"primary\" size=\"sm\" shape=\"cut\" onClick={onUpdate}>\n {updateLabel}\n </Button>\n </div>\n </section>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/update-prompt/update-prompt.tsx"],"sourcesContent":["// Server-safe. The soft invitation to update: a dismissible banner, in the flow of the page, never a blocker.\n// Every word is a prop (the app passes them translated); the version and the store URL come from `useAppConfig`.\nimport { Button } from \"@krizaka/ui/button\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const updatePrompt = tv({\n slots: {\n root: \"flex w-full flex-wrap items-center gap-3 rounded-xl border border-border-default bg-surface-1 p-4 text-sm text-fg\",\n mark: \"flex h-10 w-10 shrink-0 items-center justify-center [&>svg]:h-10 [&>svg]:w-10\",\n content: \"flex min-w-0 flex-1 flex-col gap-0.5\",\n title: \"font-semibold text-fg\",\n message: \"text-fg-secondary\",\n version: \"font-mono text-xs text-fg-tertiary\",\n actions: \"flex shrink-0 items-center gap-2\",\n },\n});\n\nexport type UpdatePromptProps = Omit<React.ComponentProps<\"section\">, \"title\"> & {\n /** The headline (“A new version is available”). */\n title: React.ReactNode;\n /** Why update, in a sentence — the backend's localized `message`. */\n message?: React.ReactNode;\n /** The versions, in words and mono (“1.2.0 → 1.4.0”). */\n versionLabel?: React.ReactNode;\n /** The product's mark (decorative), e.g. `<OrazakaLogo />`. */\n mark?: React.ReactNode;\n /** The button that updates (“Update”). */\n updateLabel: string;\n /** Opens the store page, or reloads the app on the new version. */\n onUpdate: () => void;\n /** The way out (“Later”). */\n laterLabel: string;\n /** Called by the way out: the hook remembers it for this version. */\n onLater: () => void;\n};\n\n/** The soft update: an invitation that can be dismissed, announced politely. */\nexport function UpdatePrompt({ title, message, versionLabel, mark, updateLabel, onUpdate, laterLabel, onLater, className, ...props }: UpdatePromptProps) {\n const s = updatePrompt();\n return (\n <section role=\"region\" aria-label={typeof title === \"string\" ? title : undefined} data-kind=\"update-soft\" className={s.root({ className })} {...props}>\n {mark && (\n <div aria-hidden className={s.mark()}>\n {mark}\n </div>\n )}\n <div className={s.content()}>\n <p className={s.title()}>{title}</p>\n {message && <p className={s.message()}>{message}</p>}\n {versionLabel && <p className={s.version()}>{versionLabel}</p>}\n </div>\n <div className={s.actions()}>\n <Button variant=\"ghost\" size=\"sm\" onClick={onLater}>\n {laterLabel}\n </Button>\n <Button variant=\"primary\" size=\"sm\" shape=\"cut\" onClick={onUpdate}>\n {updateLabel}\n </Button>\n </div>\n </section>\n );\n}\n"],"mappings":";;;;;;;;;AAIA,SAAS,UAAU;AAuCX,cAIF,YAJE;AArCD,IAAM,eAAe,GAAG;AAAA,EAC7B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACF,CAAC;AAsBM,SAAS,aAAa,EAAE,OAAO,SAAS,cAAc,MAAM,aAAa,UAAU,YAAY,SAAS,WAAW,GAAG,MAAM,GAAsB;AACvJ,QAAM,IAAI,aAAa;AACvB,SACE,qBAAC,aAAQ,MAAK,UAAS,cAAY,OAAO,UAAU,WAAW,QAAQ,QAAW,aAAU,eAAc,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC7I;AAAA,YACC,oBAAC,SAAI,eAAW,MAAC,WAAW,EAAE,KAAK,GAChC,gBACH;AAAA,IAEF,qBAAC,SAAI,WAAW,EAAE,QAAQ,GACxB;AAAA,0BAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,MAC/B,WAAW,oBAAC,OAAE,WAAW,EAAE,QAAQ,GAAI,mBAAQ;AAAA,MAC/C,gBAAgB,oBAAC,OAAE,WAAW,EAAE,QAAQ,GAAI,wBAAa;AAAA,OAC5D;AAAA,IACA,qBAAC,SAAI,WAAW,EAAE,QAAQ,GACxB;AAAA,0BAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,SACxC,sBACH;AAAA,MACA,oBAAC,UAAO,SAAQ,WAAU,MAAK,MAAK,OAAM,OAAM,SAAS,UACtD,uBACH;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
|
package/dist/vertical-video.js
CHANGED
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
} from "./chunk-KB7OLYIJ.js";
|
|
5
5
|
import {
|
|
6
6
|
IconButton
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DZU6RMYD.js";
|
|
8
8
|
import "./chunk-D3T54RSL.js";
|
|
9
9
|
import {
|
|
10
10
|
cn
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-NSLXEDIS.js";
|
|
12
12
|
|
|
13
13
|
// src/vertical-video/short-feed.tsx
|
|
14
14
|
import * as React from "react";
|
package/dist/video-player.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
Slider
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-KM6VAKIE.js";
|
|
5
|
+
import "./chunk-HJFRHYCI.js";
|
|
6
|
+
import "./chunk-NSLXEDIS.js";
|
|
7
7
|
import {
|
|
8
8
|
clamp,
|
|
9
9
|
formatClock,
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
declare const waveform: tailwind_variants.TVReturnType<{
|
|
5
|
+
size: {
|
|
6
|
+
sm: {
|
|
7
|
+
root: string;
|
|
8
|
+
};
|
|
9
|
+
md: {
|
|
10
|
+
root: string;
|
|
11
|
+
};
|
|
12
|
+
lg: {
|
|
13
|
+
root: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
tone: {
|
|
17
|
+
accent: {
|
|
18
|
+
bar: string;
|
|
19
|
+
};
|
|
20
|
+
neutral: {
|
|
21
|
+
bar: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}, {
|
|
25
|
+
root: string;
|
|
26
|
+
bar: string;
|
|
27
|
+
}, undefined, {
|
|
28
|
+
size: {
|
|
29
|
+
sm: {
|
|
30
|
+
root: string;
|
|
31
|
+
};
|
|
32
|
+
md: {
|
|
33
|
+
root: string;
|
|
34
|
+
};
|
|
35
|
+
lg: {
|
|
36
|
+
root: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
tone: {
|
|
40
|
+
accent: {
|
|
41
|
+
bar: string;
|
|
42
|
+
};
|
|
43
|
+
neutral: {
|
|
44
|
+
bar: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
}, {
|
|
48
|
+
root: string;
|
|
49
|
+
bar: string;
|
|
50
|
+
}, tailwind_variants.TVReturnTypeLike<{
|
|
51
|
+
size: {
|
|
52
|
+
sm: {
|
|
53
|
+
root: string;
|
|
54
|
+
};
|
|
55
|
+
md: {
|
|
56
|
+
root: string;
|
|
57
|
+
};
|
|
58
|
+
lg: {
|
|
59
|
+
root: string;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
tone: {
|
|
63
|
+
accent: {
|
|
64
|
+
bar: string;
|
|
65
|
+
};
|
|
66
|
+
neutral: {
|
|
67
|
+
bar: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
}, {
|
|
71
|
+
root: string;
|
|
72
|
+
bar: string;
|
|
73
|
+
}>>;
|
|
74
|
+
type WaveformProps = {
|
|
75
|
+
/** The peaks, between 0 and 1, as many as you like (resampled to `bars`). Without them: a flat line. */
|
|
76
|
+
peaks?: readonly number[];
|
|
77
|
+
/** How many bars. Default 32. */
|
|
78
|
+
bars?: number;
|
|
79
|
+
/** sm · md (default) · lg: the height of the drawing. */
|
|
80
|
+
size?: "sm" | "md" | "lg";
|
|
81
|
+
/** accent (default, the brand's colour) · neutral (a quiet line beside text). */
|
|
82
|
+
tone?: "accent" | "neutral";
|
|
83
|
+
/** Moves gently while `true` (a sound playing); still otherwise. */
|
|
84
|
+
playing?: boolean;
|
|
85
|
+
/** When given, it is an image named by this (“Voice note, 0:42”); otherwise decorative and hidden from assistive technology. */
|
|
86
|
+
label?: string;
|
|
87
|
+
/** Classes merged last. */
|
|
88
|
+
className?: string;
|
|
89
|
+
};
|
|
90
|
+
/** A decorative waveform: the bars of a sound, in the accent or a neutral tone, breathing gently while it plays. */
|
|
91
|
+
declare function Waveform({ peaks, bars, size, tone, playing, label, className }: WaveformProps): React.JSX.Element;
|
|
92
|
+
|
|
93
|
+
export { Waveform, type WaveformProps, waveform };
|
package/dist/waveform.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// src/waveform/waveform.tsx
|
|
2
|
+
import * as React2 from "react";
|
|
3
|
+
import { tv } from "tailwind-variants";
|
|
4
|
+
|
|
5
|
+
// src/media.ts
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
function useLatest(value) {
|
|
8
|
+
const ref = React.useRef(value);
|
|
9
|
+
React.useLayoutEffect(() => {
|
|
10
|
+
ref.current = value;
|
|
11
|
+
});
|
|
12
|
+
return ref;
|
|
13
|
+
}
|
|
14
|
+
function useInView(ref, onChange, enabled = true, threshold = 0.25) {
|
|
15
|
+
const latest = useLatest(onChange);
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
const element = ref.current;
|
|
18
|
+
if (!enabled || !element || typeof IntersectionObserver === "undefined") return;
|
|
19
|
+
const observer = new IntersectionObserver(([entry]) => entry && latest.current(entry.isIntersecting), { threshold });
|
|
20
|
+
observer.observe(element);
|
|
21
|
+
return () => observer.disconnect();
|
|
22
|
+
}, [ref, enabled, threshold, latest]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/waveform/bars.ts
|
|
26
|
+
function resamplePeaks(peaks, count) {
|
|
27
|
+
if (peaks.length === 0) return Array.from({ length: count }, () => 0.15);
|
|
28
|
+
const out = Array.from({ length: count }, (_, i) => {
|
|
29
|
+
const from = Math.floor(i / count * peaks.length);
|
|
30
|
+
const to = Math.max(from + 1, Math.floor((i + 1) / count * peaks.length));
|
|
31
|
+
return Math.max(...peaks.slice(from, to).map(Math.abs));
|
|
32
|
+
});
|
|
33
|
+
const loudest = Math.max(...out, 1e-4);
|
|
34
|
+
return out.map((v) => Math.max(0.08, v / loudest));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/waveform/waveform.tsx
|
|
38
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
39
|
+
var waveform = tv({
|
|
40
|
+
slots: {
|
|
41
|
+
root: "flex w-full items-center justify-center gap-[2px]",
|
|
42
|
+
bar: "min-w-[2px] flex-1 rounded-full"
|
|
43
|
+
},
|
|
44
|
+
variants: {
|
|
45
|
+
size: {
|
|
46
|
+
sm: { root: "h-6" },
|
|
47
|
+
md: { root: "h-10" },
|
|
48
|
+
lg: { root: "h-16" }
|
|
49
|
+
},
|
|
50
|
+
tone: {
|
|
51
|
+
accent: { bar: "bg-accent" },
|
|
52
|
+
neutral: { bar: "bg-border-strong" }
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
defaultVariants: { size: "md", tone: "accent" }
|
|
56
|
+
});
|
|
57
|
+
var MOTION = "@keyframes kz-wave{0%,100%{transform:scaleY(.45)}50%{transform:scaleY(1)}}@media (prefers-reduced-motion: no-preference){.kz-wave[data-playing] [data-bar]{animation:kz-wave 1.6s ease-in-out infinite;animation-delay:var(--kz-wave-delay,0s)}}.kz-wave[data-paused] [data-bar]{animation-play-state:paused}";
|
|
58
|
+
function Waveform({ peaks, bars = 32, size, tone, playing = false, label, className }) {
|
|
59
|
+
const s = waveform({ size, tone });
|
|
60
|
+
const root = React2.useRef(null);
|
|
61
|
+
const [visible, setVisible] = React2.useState(true);
|
|
62
|
+
useInView(root, setVisible, playing);
|
|
63
|
+
const shape = React2.useMemo(() => resamplePeaks(peaks ?? [], bars), [peaks, bars]);
|
|
64
|
+
const labelled = label !== void 0;
|
|
65
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
66
|
+
/* @__PURE__ */ jsx("style", { children: MOTION }),
|
|
67
|
+
/* @__PURE__ */ jsx(
|
|
68
|
+
"div",
|
|
69
|
+
{
|
|
70
|
+
ref: root,
|
|
71
|
+
className: s.root({ className: ["kz-wave", className].filter(Boolean).join(" ") }),
|
|
72
|
+
"data-playing": playing || void 0,
|
|
73
|
+
"data-paused": playing && !visible ? "" : void 0,
|
|
74
|
+
role: labelled ? "img" : void 0,
|
|
75
|
+
"aria-label": label,
|
|
76
|
+
"aria-hidden": labelled ? void 0 : true,
|
|
77
|
+
children: shape.map((peak, i) => /* @__PURE__ */ jsx(
|
|
78
|
+
"span",
|
|
79
|
+
{
|
|
80
|
+
"data-bar": true,
|
|
81
|
+
"aria-hidden": true,
|
|
82
|
+
className: s.bar(),
|
|
83
|
+
style: { height: `${Math.round(peak * 100)}%`, "--kz-wave-delay": `${-(i * 7 % 11) * 0.14}s` }
|
|
84
|
+
},
|
|
85
|
+
i
|
|
86
|
+
))
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
] });
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
Waveform,
|
|
93
|
+
waveform
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=waveform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/waveform/waveform.tsx","../src/media.ts","../src/waveform/bars.ts"],"sourcesContent":["// Client (the idle motion and the pause off screen). The bars of an AudioPlayer, drawn on their own: a decorative\n// waveform for a card, a banner or a sound's identity. Hidden from assistive technology unless it has a `label`.\n// Its motion runs only while `playing`, never under prefers-reduced-motion, and pauses when it leaves the screen.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { useInView } from \"../media\";\nimport { resamplePeaks } from \"./bars\";\n\nexport const waveform = tv({\n slots: {\n root: \"flex w-full items-center justify-center gap-[2px]\",\n bar: \"min-w-[2px] flex-1 rounded-full\",\n },\n variants: {\n size: {\n sm: { root: \"h-6\" },\n md: { root: \"h-10\" },\n lg: { root: \"h-16\" },\n },\n tone: {\n accent: { bar: \"bg-accent\" },\n neutral: { bar: \"bg-border-strong\" },\n },\n },\n defaultVariants: { size: \"md\", tone: \"accent\" },\n});\n\n// The idle motion: each bar breathes between 45 % and its height, staggered by its index. It is declared under a\n// no-preference query only, so a reduced-motion reader gets the still bars; `data-paused` holds it off screen.\nconst MOTION =\n \"@keyframes kz-wave{0%,100%{transform:scaleY(.45)}50%{transform:scaleY(1)}}\" +\n \"@media (prefers-reduced-motion: no-preference){.kz-wave[data-playing] [data-bar]{animation:kz-wave 1.6s ease-in-out infinite;animation-delay:var(--kz-wave-delay,0s)}}\" +\n \".kz-wave[data-paused] [data-bar]{animation-play-state:paused}\";\n\nexport type WaveformProps = {\n /** The peaks, between 0 and 1, as many as you like (resampled to `bars`). Without them: a flat line. */\n peaks?: readonly number[];\n /** How many bars. Default 32. */\n bars?: number;\n /** sm · md (default) · lg: the height of the drawing. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** accent (default, the brand's colour) · neutral (a quiet line beside text). */\n tone?: \"accent\" | \"neutral\";\n /** Moves gently while `true` (a sound playing); still otherwise. */\n playing?: boolean;\n /** When given, it is an image named by this (“Voice note, 0:42”); otherwise decorative and hidden from assistive technology. */\n label?: string;\n /** Classes merged last. */\n className?: string;\n};\n\n/** A decorative waveform: the bars of a sound, in the accent or a neutral tone, breathing gently while it plays. */\nexport function Waveform({ peaks, bars = 32, size, tone, playing = false, label, className }: WaveformProps) {\n const s = waveform({ size, tone });\n const root = React.useRef<HTMLDivElement>(null);\n const [visible, setVisible] = React.useState(true);\n useInView(root, setVisible, playing);\n const shape = React.useMemo(() => resamplePeaks(peaks ?? [], bars), [peaks, bars]);\n const labelled = label !== undefined;\n\n return (\n <>\n <style>{MOTION}</style>\n <div\n ref={root}\n className={s.root({ className: [\"kz-wave\", className].filter(Boolean).join(\" \") })}\n data-playing={playing || undefined}\n data-paused={playing && !visible ? \"\" : undefined}\n role={labelled ? \"img\" : undefined}\n aria-label={label}\n aria-hidden={labelled ? undefined : true}\n >\n {shape.map((peak, i) => (\n <span\n key={i}\n data-bar\n aria-hidden\n className={s.bar()}\n style={{ height: `${Math.round(peak * 100)}%`, \"--kz-wave-delay\": `${-((i * 7) % 11) * 0.14}s` } as React.CSSProperties}\n />\n ))}\n </div>\n </>\n );\n}\n","// 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 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","// The bars of a waveform, shared by AudioPlayer (the seekable one) and Waveform (the decorative one). Pure: no React.\n\n/** Resamples peaks to `count` bars (the maximum of each slice), normalised to the loudest. No peaks: a flat line at 15 %. */\nexport function resamplePeaks(peaks: readonly number[], count: number): number[] {\n if (peaks.length === 0) return Array.from({ length: count }, () => 0.15);\n const out = Array.from({ length: count }, (_, i) => {\n const from = Math.floor((i / count) * peaks.length);\n const to = Math.max(from + 1, Math.floor(((i + 1) / count) * peaks.length));\n return Math.max(...peaks.slice(from, to).map(Math.abs));\n });\n const loudest = Math.max(...out, 0.0001);\n return out.map((v) => Math.max(0.08, v / loudest));\n}\n"],"mappings":"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","names":["React"]}
|