@spatika/react 1.0.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 +72 -0
- package/dist/composites/ActionBar.d.ts +7 -0
- package/dist/composites/ActionBar.d.ts.map +1 -0
- package/dist/composites/ActionBar.js +5 -0
- package/dist/composites/AmountInput.d.ts +10 -0
- package/dist/composites/AmountInput.d.ts.map +1 -0
- package/dist/composites/AmountInput.js +7 -0
- package/dist/composites/AppHeader.d.ts +25 -0
- package/dist/composites/AppHeader.d.ts.map +1 -0
- package/dist/composites/AppHeader.js +13 -0
- package/dist/composites/AppSidebar.d.ts +30 -0
- package/dist/composites/AppSidebar.d.ts.map +1 -0
- package/dist/composites/AppSidebar.js +15 -0
- package/dist/composites/BottomSheet.d.ts +36 -0
- package/dist/composites/BottomSheet.d.ts.map +1 -0
- package/dist/composites/BottomSheet.js +37 -0
- package/dist/composites/Breadcrumb.d.ts +10 -0
- package/dist/composites/Breadcrumb.d.ts.map +1 -0
- package/dist/composites/Breadcrumb.js +10 -0
- package/dist/composites/Callout.d.ts +8 -0
- package/dist/composites/Callout.d.ts.map +1 -0
- package/dist/composites/Callout.js +5 -0
- package/dist/composites/Card.d.ts +31 -0
- package/dist/composites/Card.d.ts.map +1 -0
- package/dist/composites/Card.js +33 -0
- package/dist/composites/Chip.d.ts +13 -0
- package/dist/composites/Chip.d.ts.map +1 -0
- package/dist/composites/Chip.js +59 -0
- package/dist/composites/ChipGroup.d.ts +23 -0
- package/dist/composites/ChipGroup.d.ts.map +1 -0
- package/dist/composites/ChipGroup.js +27 -0
- package/dist/composites/CommandSearchField.d.ts +27 -0
- package/dist/composites/CommandSearchField.d.ts.map +1 -0
- package/dist/composites/CommandSearchField.js +17 -0
- package/dist/composites/CoverHero.d.ts +51 -0
- package/dist/composites/CoverHero.d.ts.map +1 -0
- package/dist/composites/CoverHero.js +71 -0
- package/dist/composites/CoverPattern.d.ts +12 -0
- package/dist/composites/CoverPattern.d.ts.map +1 -0
- package/dist/composites/CoverPattern.js +14 -0
- package/dist/composites/DataTableToolbar.d.ts +13 -0
- package/dist/composites/DataTableToolbar.d.ts.map +1 -0
- package/dist/composites/DataTableToolbar.js +7 -0
- package/dist/composites/DividerLabel.d.ts +5 -0
- package/dist/composites/DividerLabel.d.ts.map +1 -0
- package/dist/composites/DividerLabel.js +5 -0
- package/dist/composites/EmptyState.d.ts +16 -0
- package/dist/composites/EmptyState.d.ts.map +1 -0
- package/dist/composites/EmptyState.js +10 -0
- package/dist/composites/EntityCard.d.ts +31 -0
- package/dist/composites/EntityCard.d.ts.map +1 -0
- package/dist/composites/EntityCard.js +21 -0
- package/dist/composites/EntityMediaCard.d.ts +25 -0
- package/dist/composites/EntityMediaCard.d.ts.map +1 -0
- package/dist/composites/EntityMediaCard.js +17 -0
- package/dist/composites/FilterSheet.d.ts +34 -0
- package/dist/composites/FilterSheet.d.ts.map +1 -0
- package/dist/composites/FilterSheet.js +36 -0
- package/dist/composites/FloatingPageChrome.d.ts +90 -0
- package/dist/composites/FloatingPageChrome.d.ts.map +1 -0
- package/dist/composites/FloatingPageChrome.js +67 -0
- package/dist/composites/FormField.d.ts +15 -0
- package/dist/composites/FormField.d.ts.map +1 -0
- package/dist/composites/FormField.js +9 -0
- package/dist/composites/GlassCard.d.ts +13 -0
- package/dist/composites/GlassCard.d.ts.map +1 -0
- package/dist/composites/GlassCard.js +32 -0
- package/dist/composites/HeaderIconButton.d.ts +13 -0
- package/dist/composites/HeaderIconButton.d.ts.map +1 -0
- package/dist/composites/HeaderIconButton.js +12 -0
- package/dist/composites/ListRow.d.ts +9 -0
- package/dist/composites/ListRow.d.ts.map +1 -0
- package/dist/composites/ListRow.js +6 -0
- package/dist/composites/MediaEntryCard.d.ts +25 -0
- package/dist/composites/MediaEntryCard.d.ts.map +1 -0
- package/dist/composites/MediaEntryCard.js +10 -0
- package/dist/composites/MobileTabBar.d.ts +33 -0
- package/dist/composites/MobileTabBar.d.ts.map +1 -0
- package/dist/composites/MobileTabBar.js +19 -0
- package/dist/composites/NotificationBell.d.ts +28 -0
- package/dist/composites/NotificationBell.d.ts.map +1 -0
- package/dist/composites/NotificationBell.js +25 -0
- package/dist/composites/PageHeader.d.ts +11 -0
- package/dist/composites/PageHeader.d.ts.map +1 -0
- package/dist/composites/PageHeader.js +6 -0
- package/dist/composites/PageShell.d.ts +12 -0
- package/dist/composites/PageShell.d.ts.map +1 -0
- package/dist/composites/PageShell.js +8 -0
- package/dist/composites/PageStickyHeader.d.ts +33 -0
- package/dist/composites/PageStickyHeader.d.ts.map +1 -0
- package/dist/composites/PageStickyHeader.js +19 -0
- package/dist/composites/Pagination.d.ts +7 -0
- package/dist/composites/Pagination.d.ts.map +1 -0
- package/dist/composites/Pagination.js +6 -0
- package/dist/composites/PhotoViewer.d.ts +18 -0
- package/dist/composites/PhotoViewer.d.ts.map +1 -0
- package/dist/composites/PhotoViewer.js +37 -0
- package/dist/composites/PinPad.d.ts +29 -0
- package/dist/composites/PinPad.d.ts.map +1 -0
- package/dist/composites/PinPad.js +58 -0
- package/dist/composites/ProfileHero.d.ts +34 -0
- package/dist/composites/ProfileHero.d.ts.map +1 -0
- package/dist/composites/ProfileHero.js +21 -0
- package/dist/composites/QuickFilterRail.d.ts +25 -0
- package/dist/composites/QuickFilterRail.d.ts.map +1 -0
- package/dist/composites/QuickFilterRail.js +18 -0
- package/dist/composites/QuickSettings.d.ts +27 -0
- package/dist/composites/QuickSettings.d.ts.map +1 -0
- package/dist/composites/QuickSettings.js +18 -0
- package/dist/composites/RichTextEditor.d.ts +13 -0
- package/dist/composites/RichTextEditor.d.ts.map +1 -0
- package/dist/composites/RichTextEditor.js +23 -0
- package/dist/composites/SearchField.d.ts +8 -0
- package/dist/composites/SearchField.d.ts.map +1 -0
- package/dist/composites/SearchField.js +8 -0
- package/dist/composites/SectionPanel.d.ts +16 -0
- package/dist/composites/SectionPanel.d.ts.map +1 -0
- package/dist/composites/SectionPanel.js +8 -0
- package/dist/composites/SegmentedControl.d.ts +17 -0
- package/dist/composites/SegmentedControl.d.ts.map +1 -0
- package/dist/composites/SegmentedControl.js +11 -0
- package/dist/composites/StatCard.d.ts +11 -0
- package/dist/composites/StatCard.d.ts.map +1 -0
- package/dist/composites/StatCard.js +6 -0
- package/dist/composites/StatusDot.d.ts +11 -0
- package/dist/composites/StatusDot.d.ts.map +1 -0
- package/dist/composites/StatusDot.js +23 -0
- package/dist/composites/SurfaceCard.d.ts +12 -0
- package/dist/composites/SurfaceCard.d.ts.map +1 -0
- package/dist/composites/SurfaceCard.js +24 -0
- package/dist/composites/Timeline.d.ts +19 -0
- package/dist/composites/Timeline.d.ts.map +1 -0
- package/dist/composites/Timeline.js +12 -0
- package/dist/composites/Toast.d.ts +26 -0
- package/dist/composites/Toast.d.ts.map +1 -0
- package/dist/composites/Toast.js +49 -0
- package/dist/composites/Toolbar.d.ts +6 -0
- package/dist/composites/Toolbar.d.ts.map +1 -0
- package/dist/composites/Toolbar.js +5 -0
- package/dist/composites/ViewFiltersPanel.d.ts +21 -0
- package/dist/composites/ViewFiltersPanel.d.ts.map +1 -0
- package/dist/composites/ViewFiltersPanel.js +11 -0
- package/dist/index.d.ts +96 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/lib/animations.d.ts +62 -0
- package/dist/lib/animations.d.ts.map +1 -0
- package/dist/lib/animations.js +37 -0
- package/dist/lib/avatar-utils.d.ts +10 -0
- package/dist/lib/avatar-utils.d.ts.map +1 -0
- package/dist/lib/avatar-utils.js +49 -0
- package/dist/lib/chips.d.ts +10 -0
- package/dist/lib/chips.d.ts.map +1 -0
- package/dist/lib/chips.js +30 -0
- package/dist/lib/cn.d.ts +4 -0
- package/dist/lib/cn.d.ts.map +1 -0
- package/dist/lib/cn.js +6 -0
- package/dist/lib/compose-refs.d.ts +6 -0
- package/dist/lib/compose-refs.d.ts.map +1 -0
- package/dist/lib/compose-refs.js +17 -0
- package/dist/lib/cover-chrome.d.ts +9 -0
- package/dist/lib/cover-chrome.d.ts.map +1 -0
- package/dist/lib/cover-chrome.js +23 -0
- package/dist/lib/cover-pattern.d.ts +75 -0
- package/dist/lib/cover-pattern.d.ts.map +1 -0
- package/dist/lib/cover-pattern.js +135 -0
- package/dist/lib/overlay-stack.d.ts +23 -0
- package/dist/lib/overlay-stack.d.ts.map +1 -0
- package/dist/lib/overlay-stack.js +37 -0
- package/dist/lib/portal.d.ts +12 -0
- package/dist/lib/portal.d.ts.map +1 -0
- package/dist/lib/portal.js +12 -0
- package/dist/lib/slot.d.ts +12 -0
- package/dist/lib/slot.d.ts.map +1 -0
- package/dist/lib/slot.js +55 -0
- package/dist/lib/surfaces.d.ts +14 -0
- package/dist/lib/surfaces.d.ts.map +1 -0
- package/dist/lib/surfaces.js +18 -0
- package/dist/lib/themes.d.ts +16 -0
- package/dist/lib/themes.d.ts.map +1 -0
- package/dist/lib/themes.js +53 -0
- package/dist/lib/typography.d.ts +17 -0
- package/dist/lib/typography.d.ts.map +1 -0
- package/dist/lib/typography.js +16 -0
- package/dist/lib/use-controllable-state.d.ts +12 -0
- package/dist/lib/use-controllable-state.d.ts.map +1 -0
- package/dist/lib/use-controllable-state.js +20 -0
- package/dist/lib/use-cover-chrome-bleed.d.ts +9 -0
- package/dist/lib/use-cover-chrome-bleed.d.ts.map +1 -0
- package/dist/lib/use-cover-chrome-bleed.js +28 -0
- package/dist/lib/use-dismissable.d.ts +13 -0
- package/dist/lib/use-dismissable.d.ts.map +1 -0
- package/dist/lib/use-dismissable.js +33 -0
- package/dist/lib/use-floating-position.d.ts +27 -0
- package/dist/lib/use-floating-position.d.ts.map +1 -0
- package/dist/lib/use-floating-position.js +115 -0
- package/dist/lib/use-focus-trap.d.ts +7 -0
- package/dist/lib/use-focus-trap.d.ts.map +1 -0
- package/dist/lib/use-focus-trap.js +61 -0
- package/dist/lib/use-media-query.d.ts +5 -0
- package/dist/lib/use-media-query.d.ts.map +1 -0
- package/dist/lib/use-media-query.js +19 -0
- package/dist/primitives/Accordion.d.ts +24 -0
- package/dist/primitives/Accordion.d.ts.map +1 -0
- package/dist/primitives/Accordion.js +37 -0
- package/dist/primitives/Alert.d.ts +10 -0
- package/dist/primitives/Alert.d.ts.map +1 -0
- package/dist/primitives/Alert.js +25 -0
- package/dist/primitives/AlertDialog.d.ts +33 -0
- package/dist/primitives/AlertDialog.d.ts.map +1 -0
- package/dist/primitives/AlertDialog.js +96 -0
- package/dist/primitives/Avatar.d.ts +15 -0
- package/dist/primitives/Avatar.d.ts.map +1 -0
- package/dist/primitives/Avatar.js +52 -0
- package/dist/primitives/Badge.d.ts +12 -0
- package/dist/primitives/Badge.d.ts.map +1 -0
- package/dist/primitives/Badge.js +27 -0
- package/dist/primitives/Button.d.ts +14 -0
- package/dist/primitives/Button.d.ts.map +1 -0
- package/dist/primitives/Button.js +37 -0
- package/dist/primitives/Checkbox.d.ts +9 -0
- package/dist/primitives/Checkbox.d.ts.map +1 -0
- package/dist/primitives/Checkbox.js +22 -0
- package/dist/primitives/Command.d.ts +17 -0
- package/dist/primitives/Command.d.ts.map +1 -0
- package/dist/primitives/Command.js +33 -0
- package/dist/primitives/Dialog.d.ts +34 -0
- package/dist/primitives/Dialog.d.ts.map +1 -0
- package/dist/primitives/Dialog.js +96 -0
- package/dist/primitives/DropdownMenu.d.ts +65 -0
- package/dist/primitives/DropdownMenu.d.ts.map +1 -0
- package/dist/primitives/DropdownMenu.js +196 -0
- package/dist/primitives/Input.d.ts +4 -0
- package/dist/primitives/Input.d.ts.map +1 -0
- package/dist/primitives/Input.js +6 -0
- package/dist/primitives/Kbd.d.ts +4 -0
- package/dist/primitives/Kbd.d.ts.map +1 -0
- package/dist/primitives/Kbd.js +6 -0
- package/dist/primitives/Label.d.ts +4 -0
- package/dist/primitives/Label.d.ts.map +1 -0
- package/dist/primitives/Label.js +6 -0
- package/dist/primitives/NativeSelect.d.ts +7 -0
- package/dist/primitives/NativeSelect.d.ts.map +1 -0
- package/dist/primitives/NativeSelect.js +10 -0
- package/dist/primitives/Popover.d.ts +29 -0
- package/dist/primitives/Popover.d.ts.map +1 -0
- package/dist/primitives/Popover.js +95 -0
- package/dist/primitives/Progress.d.ts +8 -0
- package/dist/primitives/Progress.d.ts.map +1 -0
- package/dist/primitives/Progress.js +7 -0
- package/dist/primitives/RadioGroup.d.ts +13 -0
- package/dist/primitives/RadioGroup.d.ts.map +1 -0
- package/dist/primitives/RadioGroup.js +33 -0
- package/dist/primitives/Select.d.ts +33 -0
- package/dist/primitives/Select.d.ts.map +1 -0
- package/dist/primitives/Select.js +178 -0
- package/dist/primitives/Separator.d.ts +7 -0
- package/dist/primitives/Separator.d.ts.map +1 -0
- package/dist/primitives/Separator.js +6 -0
- package/dist/primitives/Sheet.d.ts +28 -0
- package/dist/primitives/Sheet.d.ts.map +1 -0
- package/dist/primitives/Sheet.js +96 -0
- package/dist/primitives/Skeleton.d.ts +4 -0
- package/dist/primitives/Skeleton.d.ts.map +1 -0
- package/dist/primitives/Skeleton.js +6 -0
- package/dist/primitives/Slider.d.ts +12 -0
- package/dist/primitives/Slider.d.ts.map +1 -0
- package/dist/primitives/Slider.js +23 -0
- package/dist/primitives/Spinner.d.ts +6 -0
- package/dist/primitives/Spinner.d.ts.map +1 -0
- package/dist/primitives/Spinner.js +7 -0
- package/dist/primitives/StarRating.d.ts +10 -0
- package/dist/primitives/StarRating.d.ts.map +1 -0
- package/dist/primitives/StarRating.js +11 -0
- package/dist/primitives/Switch.d.ts +8 -0
- package/dist/primitives/Switch.d.ts.map +1 -0
- package/dist/primitives/Switch.js +20 -0
- package/dist/primitives/Table.d.ts +13 -0
- package/dist/primitives/Table.d.ts.map +1 -0
- package/dist/primitives/Table.js +20 -0
- package/dist/primitives/Tabs.d.ts +17 -0
- package/dist/primitives/Tabs.d.ts.map +1 -0
- package/dist/primitives/Tabs.js +30 -0
- package/dist/primitives/Textarea.d.ts +4 -0
- package/dist/primitives/Textarea.d.ts.map +1 -0
- package/dist/primitives/Textarea.js +6 -0
- package/dist/primitives/Tooltip.d.ts +31 -0
- package/dist/primitives/Tooltip.d.ts.map +1 -0
- package/dist/primitives/Tooltip.js +94 -0
- package/dist/theme/OriginThemeProvider.d.ts +31 -0
- package/dist/theme/OriginThemeProvider.d.ts.map +1 -0
- package/dist/theme/OriginThemeProvider.js +37 -0
- package/dist/theme/SpatikaThemeProvider.d.ts +36 -0
- package/dist/theme/SpatikaThemeProvider.d.ts.map +1 -0
- package/dist/theme/SpatikaThemeProvider.js +38 -0
- package/package.json +58 -0
- package/src/composites/ActionBar.tsx +25 -0
- package/src/composites/AmountInput.tsx +40 -0
- package/src/composites/AppHeader.tsx +88 -0
- package/src/composites/AppSidebar.tsx +120 -0
- package/src/composites/BottomSheet.tsx +179 -0
- package/src/composites/Breadcrumb.tsx +42 -0
- package/src/composites/Callout.tsx +22 -0
- package/src/composites/Card.tsx +119 -0
- package/src/composites/Chip.tsx +87 -0
- package/src/composites/ChipGroup.component.test.tsx +31 -0
- package/src/composites/ChipGroup.test.ts +16 -0
- package/src/composites/ChipGroup.tsx +86 -0
- package/src/composites/CommandSearchField.tsx +124 -0
- package/src/composites/CoverHero.tsx +359 -0
- package/src/composites/CoverPattern.tsx +90 -0
- package/src/composites/DataTableToolbar.tsx +48 -0
- package/src/composites/DividerLabel.tsx +22 -0
- package/src/composites/EmptyState.tsx +55 -0
- package/src/composites/EntityCard.tsx +100 -0
- package/src/composites/EntityMediaCard.tsx +118 -0
- package/src/composites/FilterSheet.tsx +178 -0
- package/src/composites/FloatingPageChrome.tsx +294 -0
- package/src/composites/FormField.tsx +44 -0
- package/src/composites/GlassCard.tsx +47 -0
- package/src/composites/HeaderIconButton.tsx +49 -0
- package/src/composites/ListRow.tsx +29 -0
- package/src/composites/MediaEntryCard.tsx +95 -0
- package/src/composites/MobileTabBar.tsx +130 -0
- package/src/composites/NotificationBell.tsx +164 -0
- package/src/composites/PageHeader.tsx +27 -0
- package/src/composites/PageShell.tsx +20 -0
- package/src/composites/PageStickyHeader.tsx +157 -0
- package/src/composites/Pagination.tsx +41 -0
- package/src/composites/PhotoViewer.tsx +142 -0
- package/src/composites/PinPad.tsx +163 -0
- package/src/composites/ProfileHero.tsx +163 -0
- package/src/composites/QuickFilterRail.tsx +92 -0
- package/src/composites/QuickSettings.tsx +120 -0
- package/src/composites/RichTextEditor.tsx +103 -0
- package/src/composites/SearchField.tsx +38 -0
- package/src/composites/SectionPanel.tsx +59 -0
- package/src/composites/SegmentedControl.tsx +62 -0
- package/src/composites/StatCard.tsx +26 -0
- package/src/composites/StatusDot.tsx +40 -0
- package/src/composites/SurfaceCard.tsx +44 -0
- package/src/composites/Timeline.tsx +70 -0
- package/src/composites/Toast.tsx +135 -0
- package/src/composites/Toolbar.tsx +19 -0
- package/src/composites/ViewFiltersPanel.tsx +82 -0
- package/src/composites/chrome.test.tsx +170 -0
- package/src/composites/smoke.test.tsx +49 -0
- package/src/index.ts +355 -0
- package/src/lib/animations.ts +47 -0
- package/src/lib/avatar-utils.ts +52 -0
- package/src/lib/chips.ts +58 -0
- package/src/lib/cn.test.ts +16 -0
- package/src/lib/cn.ts +7 -0
- package/src/lib/compose-refs.ts +21 -0
- package/src/lib/cover-chrome.ts +31 -0
- package/src/lib/cover-pattern.ts +242 -0
- package/src/lib/overlay-stack.ts +44 -0
- package/src/lib/portal.tsx +21 -0
- package/src/lib/slot.tsx +69 -0
- package/src/lib/surfaces.ts +57 -0
- package/src/lib/themes.test.ts +73 -0
- package/src/lib/themes.ts +59 -0
- package/src/lib/tokens.test.ts +52 -0
- package/src/lib/typography.ts +27 -0
- package/src/lib/use-controllable-state.ts +38 -0
- package/src/lib/use-cover-chrome-bleed.ts +33 -0
- package/src/lib/use-dismissable.ts +49 -0
- package/src/lib/use-floating-position.ts +168 -0
- package/src/lib/use-focus-trap.ts +73 -0
- package/src/lib/use-media-query.ts +22 -0
- package/src/primitives/Accordion.tsx +114 -0
- package/src/primitives/Alert.tsx +57 -0
- package/src/primitives/AlertDialog.tsx +270 -0
- package/src/primitives/Avatar.tsx +140 -0
- package/src/primitives/Badge.test.tsx +15 -0
- package/src/primitives/Badge.tsx +43 -0
- package/src/primitives/Button.test.tsx +37 -0
- package/src/primitives/Button.tsx +58 -0
- package/src/primitives/Checkbox.tsx +75 -0
- package/src/primitives/Command.tsx +175 -0
- package/src/primitives/Dialog.tsx +241 -0
- package/src/primitives/DropdownMenu.tsx +552 -0
- package/src/primitives/Input.test.tsx +22 -0
- package/src/primitives/Input.tsx +22 -0
- package/src/primitives/Kbd.tsx +17 -0
- package/src/primitives/Label.tsx +20 -0
- package/src/primitives/NativeSelect.tsx +22 -0
- package/src/primitives/Popover.tsx +209 -0
- package/src/primitives/Progress.tsx +31 -0
- package/src/primitives/RadioGroup.tsx +116 -0
- package/src/primitives/Select.tsx +409 -0
- package/src/primitives/Separator.tsx +30 -0
- package/src/primitives/Sheet.tsx +265 -0
- package/src/primitives/Skeleton.tsx +16 -0
- package/src/primitives/Slider.tsx +97 -0
- package/src/primitives/Spinner.tsx +21 -0
- package/src/primitives/StarRating.tsx +53 -0
- package/src/primitives/Switch.tsx +68 -0
- package/src/primitives/Table.tsx +134 -0
- package/src/primitives/Tabs.tsx +97 -0
- package/src/primitives/Textarea.tsx +20 -0
- package/src/primitives/Tooltip.tsx +193 -0
- package/src/primitives/smoke.test.tsx +34 -0
- package/src/test/setup.ts +1 -0
- package/src/theme/SpatikaThemeProvider.test.tsx +82 -0
- package/src/theme/SpatikaThemeProvider.tsx +112 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { coverFloatingIconClass } from "../lib/cover-chrome";
|
|
3
|
+
import { type CoverPatternKind } from "../lib/cover-pattern";
|
|
4
|
+
export type CoverHeroAvatar = {
|
|
5
|
+
name: string;
|
|
6
|
+
src?: string;
|
|
7
|
+
href?: string;
|
|
8
|
+
onClick?: () => void;
|
|
9
|
+
};
|
|
10
|
+
export type CoverHeroFact = {
|
|
11
|
+
key: string;
|
|
12
|
+
label: string;
|
|
13
|
+
value: ReactNode;
|
|
14
|
+
icon?: ReactNode;
|
|
15
|
+
wide?: boolean;
|
|
16
|
+
muted?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type CoverHeroProps = {
|
|
19
|
+
title: string;
|
|
20
|
+
kicker?: ReactNode;
|
|
21
|
+
facts?: CoverHeroFact[];
|
|
22
|
+
avatars?: CoverHeroAvatar[];
|
|
23
|
+
hiddenAvatarCount?: number;
|
|
24
|
+
coverUrl?: string;
|
|
25
|
+
hideImages?: boolean;
|
|
26
|
+
coverSeed?: string;
|
|
27
|
+
coverHue?: number;
|
|
28
|
+
coverKind?: CoverPatternKind | null;
|
|
29
|
+
dark?: boolean;
|
|
30
|
+
warm?: boolean;
|
|
31
|
+
/** Profile bleeds into a tab bar; story ends at the identity plate. */
|
|
32
|
+
variant?: "story" | "profile";
|
|
33
|
+
onBack?: () => void;
|
|
34
|
+
backLabel?: string;
|
|
35
|
+
floatingActions?: ReactNode;
|
|
36
|
+
compactActions?: ReactNode;
|
|
37
|
+
children?: ReactNode;
|
|
38
|
+
className?: string;
|
|
39
|
+
/** Offset used when the compact bar pins under app chrome. */
|
|
40
|
+
compactOffsetClassName?: string;
|
|
41
|
+
/** When false, skip writing cover-bleed attributes on `<html>` (catalog previews). */
|
|
42
|
+
bleed?: boolean;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Cover hero — generated / photo cover that bleeds into app chrome, floating
|
|
46
|
+
* glass controls, a notched identity plate, and a compact sticky bar once the
|
|
47
|
+
* hero scrolls away. Mirrors journalD StoryCoverHeader / Profile hero.
|
|
48
|
+
*/
|
|
49
|
+
export declare function CoverHero({ title, kicker, facts, avatars, hiddenAvatarCount, coverUrl, hideImages, coverSeed, coverHue, coverKind, dark, warm, variant, onBack, backLabel, floatingActions, compactActions, children, className, compactOffsetClassName, bleed, }: CoverHeroProps): import("react").JSX.Element;
|
|
50
|
+
export { coverFloatingIconClass };
|
|
51
|
+
//# sourceMappingURL=CoverHero.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoverHero.d.ts","sourceRoot":"","sources":["../../src/composites/CoverHero.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,EACL,sBAAsB,EAIvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAK9B,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sFAAsF;IACtF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,MAAM,EACN,KAAK,EACL,OAAY,EACZ,iBAAqB,EACrB,QAAQ,EACR,UAAU,EACV,SAAS,EACT,QAAc,EACd,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,OAAiB,EACjB,MAAM,EACN,SAAqB,EACrB,eAAe,EACf,cAAc,EACd,QAAQ,EACR,SAAS,EACT,sBAAiC,EACjC,KAAY,GACb,EAAE,cAAc,+BAuQhB;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState, } from "react";
|
|
3
|
+
import { ChevronLeft } from "lucide-react";
|
|
4
|
+
import { cn } from "../lib/cn";
|
|
5
|
+
import { coverFloatingIconClass, coverMutedClass, coverPlateClass, coverTitleClass, } from "../lib/cover-chrome";
|
|
6
|
+
import { getCoverPattern, } from "../lib/cover-pattern";
|
|
7
|
+
import { useCoverChromeBleed } from "../lib/use-cover-chrome-bleed";
|
|
8
|
+
import { getInitials } from "../lib/avatar-utils";
|
|
9
|
+
import { CoverPattern } from "./CoverPattern";
|
|
10
|
+
/**
|
|
11
|
+
* Cover hero — generated / photo cover that bleeds into app chrome, floating
|
|
12
|
+
* glass controls, a notched identity plate, and a compact sticky bar once the
|
|
13
|
+
* hero scrolls away. Mirrors journalD StoryCoverHeader / Profile hero.
|
|
14
|
+
*/
|
|
15
|
+
export function CoverHero({ title, kicker, facts, avatars = [], hiddenAvatarCount = 0, coverUrl, hideImages, coverSeed, coverHue = 210, coverKind, dark, warm, variant = "story", onBack, backLabel = "Go back", floatingActions, compactActions, children, className, compactOffsetClassName = "top-16", bleed = true, }) {
|
|
16
|
+
const seed = coverSeed ?? title;
|
|
17
|
+
const scene = getCoverPattern({ seed, hue: coverHue, dark, warm, kind: coverKind });
|
|
18
|
+
const onDarkCover = scene.headerInk === "light";
|
|
19
|
+
const mediaClass = variant === "profile" ? "cover-media cover-media--profile" : "cover-media cover-media--story";
|
|
20
|
+
const visibleAvatars = avatars.slice(0, 3);
|
|
21
|
+
const extra = Math.max(0, hiddenAvatarCount || avatars.length - visibleAvatars.length);
|
|
22
|
+
const avatarCount = visibleAvatars.length + (extra > 0 ? 1 : 0);
|
|
23
|
+
const hasAvatars = avatarCount > 0;
|
|
24
|
+
const heroRef = useRef(null);
|
|
25
|
+
const plateRef = useRef(null);
|
|
26
|
+
const [coverUnderChrome, setCoverUnderChrome] = useState(true);
|
|
27
|
+
const [heroInView, setHeroInView] = useState(true);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
let frame = 0;
|
|
30
|
+
const measure = () => {
|
|
31
|
+
frame = 0;
|
|
32
|
+
const hero = heroRef.current;
|
|
33
|
+
const plate = plateRef.current;
|
|
34
|
+
if (!hero || !plate)
|
|
35
|
+
return;
|
|
36
|
+
const chromeHeight = document.querySelector(".app-chrome-header")?.offsetHeight ?? 64;
|
|
37
|
+
const heroRect = hero.getBoundingClientRect();
|
|
38
|
+
if (heroRect.height === 0)
|
|
39
|
+
return;
|
|
40
|
+
setCoverUnderChrome(plate.getBoundingClientRect().top > chromeHeight + 1);
|
|
41
|
+
setHeroInView(heroRect.bottom > chromeHeight + 1);
|
|
42
|
+
};
|
|
43
|
+
const schedule = () => {
|
|
44
|
+
if (!frame)
|
|
45
|
+
frame = window.requestAnimationFrame(measure);
|
|
46
|
+
};
|
|
47
|
+
measure();
|
|
48
|
+
window.addEventListener("scroll", schedule, { passive: true });
|
|
49
|
+
window.addEventListener("resize", schedule);
|
|
50
|
+
return () => {
|
|
51
|
+
if (frame)
|
|
52
|
+
window.cancelAnimationFrame(frame);
|
|
53
|
+
window.removeEventListener("scroll", schedule);
|
|
54
|
+
window.removeEventListener("resize", schedule);
|
|
55
|
+
};
|
|
56
|
+
}, []);
|
|
57
|
+
useCoverChromeBleed(bleed && coverUnderChrome, scene.chromeInk);
|
|
58
|
+
return (_jsxs(_Fragment, { children: [_jsxs("header", { ref: heroRef, "data-slot": "cover-hero", className: cn("relative z-10 w-full overflow-visible", className), children: [_jsxs("div", { className: cn(mediaClass, "sm:rounded-b-[1.75rem]"), "aria-hidden": true, children: [!hideImages && coverUrl ? (_jsx("img", { src: coverUrl, alt: "", className: "absolute inset-0 size-full object-cover" })) : (_jsx(CoverPattern, { seed: seed, hue: coverHue, dark: dark, warm: warm, kind: coverKind })), _jsx("div", { className: "absolute inset-x-0 top-0 h-8 bg-gradient-to-b from-black/[0.04] to-transparent dark:from-black/12" }), _jsx("div", { className: "absolute inset-x-0 bottom-0 h-[22%] bg-gradient-to-t from-black/[0.03] via-transparent to-transparent dark:from-black/10" })] }), _jsxs("div", { className: "relative z-10 flex flex-col", children: [_jsx("div", { className: "relative min-h-[8.5rem] sm:min-h-[10.5rem] lg:min-h-[12rem]", children: _jsxs("div", { className: "absolute inset-x-0 top-0 z-30 flex items-start justify-between gap-2 px-3 pt-3 sm:px-5 sm:pt-4", children: [onBack ? (_jsxs("button", { type: "button", onClick: onBack, "aria-label": backLabel, "data-cover-ink": scene.headerInk, className: cn("cover-floating-shell flex items-center gap-1 px-3 py-1.5 text-xs font-semibold transition-colors active:scale-[0.96]", onDarkCover ? "text-white hover:bg-black/60" : "text-zinc-900 hover:bg-white/90"), children: [_jsx(ChevronLeft, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }), _jsx("span", { className: "hidden sm:inline", children: "Back" })] })) : (_jsx("span", {})), floatingActions ? (_jsx("div", { "data-cover-ink": scene.headerInk, className: "cover-floating-shell flex items-center gap-1 p-1", children: floatingActions })) : null] }) }), _jsx("div", { ref: plateRef, className: "relative z-20 px-3.5 pb-4 sm:px-5 sm:pb-5 lg:px-8 lg:pb-6", children: _jsxs("div", { className: "cover-identity story-identity", style: { "--story-avatar-count": avatarCount }, children: [_jsx("div", { "aria-hidden": true, className: cn("pointer-events-none absolute inset-0 rounded-[1.35rem]", hasAvatars && "cover-identity__plate story-identity__plate", coverPlateClass(scene.headerInk)) }), _jsxs("div", { className: cn("relative z-10 flex flex-col items-center px-3 pb-3 text-center sm:px-6 sm:pb-4", hasAvatars ? "pt-0" : "pt-3 sm:pt-4"), children: [hasAvatars ? (_jsx("div", { className: "cover-identity__avatars story-identity__avatars", children: _jsxs("div", { className: "flex -space-x-5 sm:-space-x-6", children: [visibleAvatars.map((avatar, index) => {
|
|
59
|
+
const body = (_jsx("span", { style: {
|
|
60
|
+
width: "var(--story-avatar-size)",
|
|
61
|
+
height: "var(--story-avatar-size)",
|
|
62
|
+
}, className: "flex items-center justify-center overflow-hidden rounded-full border-[3px] border-white bg-muted text-lg font-black text-primary shadow-[0_16px_40px_rgba(0,0,0,0.38)] dark:border-white/30", children: !hideImages && avatar.src ? (_jsx("img", { src: avatar.src, alt: "", className: "size-full object-cover" })) : (getInitials(avatar.name)) }));
|
|
63
|
+
return (_jsx("span", { style: { zIndex: visibleAvatars.length - index }, className: "relative", children: avatar.href ? (_jsx("a", { href: avatar.href, onClick: avatar.onClick, title: avatar.name, "aria-label": avatar.name, className: "block rounded-full outline-none focus-visible:ring-2 focus-visible:ring-primary/60", children: body })) : (_jsx("button", { type: "button", onClick: avatar.onClick, title: avatar.name, "aria-label": avatar.name, className: "block rounded-full outline-none focus-visible:ring-2 focus-visible:ring-primary/60", children: body })) }, avatar.name + index));
|
|
64
|
+
}), extra > 0 ? (_jsxs("span", { style: {
|
|
65
|
+
width: "var(--story-avatar-size)",
|
|
66
|
+
height: "var(--story-avatar-size)",
|
|
67
|
+
}, className: "relative z-0 flex items-center justify-center rounded-full border-[3px] border-white bg-zinc-900/80 text-base font-black text-white dark:border-white/30", children: ["+", extra] })) : null] }) })) : null, _jsxs("div", { className: cn("w-full min-w-0", hasAvatars && "mt-2 sm:mt-2.5"), children: [kicker ? (_jsx("div", { className: "flex flex-wrap items-center justify-center gap-1.5", children: kicker })) : null, _jsx("h1", { className: cn("mt-2 text-balance text-[1.15rem] font-black leading-tight tracking-tight sm:text-[1.35rem] lg:text-[1.65rem]", coverTitleClass(scene.headerInk)), children: title }), facts && facts.length > 0 ? (_jsx("dl", { className: "mt-3 grid grid-cols-2 gap-x-4 gap-y-2 sm:flex sm:flex-wrap sm:justify-center sm:gap-x-6", children: facts.map((fact) => (_jsxs("div", { className: cn("flex min-w-0 items-center justify-center gap-2", fact.wide && "col-span-2 sm:col-span-1"), children: [fact.icon ? (_jsx("span", { className: cn("hidden h-7 w-7 shrink-0 items-center justify-center rounded-lg border backdrop-blur-md sm:flex", onDarkCover
|
|
68
|
+
? "border-white/20 bg-white/15 text-white/90"
|
|
69
|
+
: "border-zinc-950/10 bg-zinc-950/[0.06] text-zinc-700"), children: fact.icon })) : null, _jsxs("div", { className: "min-w-0 text-center sm:text-left", children: [_jsx("dt", { className: cn("text-[9px] font-black uppercase tracking-[0.18em]", coverMutedClass(scene.headerInk)), children: fact.label }), _jsx("dd", { className: cn("truncate text-[11px] font-bold sm:text-xs", coverTitleClass(scene.headerInk), fact.muted && "opacity-60"), children: fact.value })] })] }, fact.key))) })) : null, children] })] })] }) })] })] }), _jsx("div", { className: cn("sticky z-[60] h-0", compactOffsetClassName), children: !heroInView ? (_jsx("div", { className: "glass-header cover-chrome-bar absolute inset-x-0 top-0 border-b border-border/50 bg-background/85 backdrop-blur-md dark:bg-background/94", children: _jsxs("div", { className: "app-frame-pad flex items-center gap-2 py-1.5 sm:py-2", children: [onBack ? (_jsx("button", { type: "button", onClick: onBack, "aria-label": backLabel, className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-xl text-foreground transition-colors hover:bg-muted", children: _jsx(ChevronLeft, { className: "h-4 w-4", "aria-hidden": true }) })) : null, _jsx("h2", { className: "page-header-title min-w-0 flex-1 truncate", children: title }), compactActions] }) })) : null })] }));
|
|
70
|
+
}
|
|
71
|
+
export { coverFloatingIconClass };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type CoverPatternInput } from "../lib/cover-pattern";
|
|
2
|
+
export type CoverPatternProps = CoverPatternInput & {
|
|
3
|
+
className?: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Seeded nature-inspired cover when no cover photo is set.
|
|
7
|
+
* Scene kind is unique per seed; colors follow hue + theme.
|
|
8
|
+
*/
|
|
9
|
+
export declare function CoverPattern({ seed, hue, secondaryHue, tertiaryHue, dark, warm, kind, className, }: CoverPatternProps): import("react").JSX.Element;
|
|
10
|
+
/** @deprecated Use CoverPattern — kept as the journalD name. */
|
|
11
|
+
export declare const ProfileCoverPattern: typeof CoverPattern;
|
|
12
|
+
//# sourceMappingURL=CoverPattern.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoverPattern.d.ts","sourceRoot":"","sources":["../../src/composites/CoverPattern.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,GAAG;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,GAAG,EACH,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,SAAS,GACV,EAAE,iBAAiB,+BA8DnB;AAED,gEAAgE;AAChE,eAAO,MAAM,mBAAmB,qBAAe,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { cn } from "../lib/cn";
|
|
4
|
+
import { getCoverPattern, } from "../lib/cover-pattern";
|
|
5
|
+
/**
|
|
6
|
+
* Seeded nature-inspired cover when no cover photo is set.
|
|
7
|
+
* Scene kind is unique per seed; colors follow hue + theme.
|
|
8
|
+
*/
|
|
9
|
+
export function CoverPattern({ seed, hue, secondaryHue, tertiaryHue, dark, warm, kind, className, }) {
|
|
10
|
+
const scene = useMemo(() => getCoverPattern({ seed, hue, secondaryHue, tertiaryHue, dark, warm, kind }), [seed, hue, secondaryHue, tertiaryHue, dark, warm, kind]);
|
|
11
|
+
return (_jsxs("div", { "data-cover-pattern": scene.kind, className: cn("absolute inset-0 overflow-hidden", className), "aria-hidden": true, children: [_jsx("div", { className: "absolute inset-0 transition-[background-color,background-image] duration-700 ease-out", style: scene.skyStyle }), _jsxs("svg", { viewBox: "0 0 1600 420", preserveAspectRatio: "xMidYMid slice", className: "absolute inset-0 size-full", children: [scene.ellipses.map((ellipse, index) => (_jsx("ellipse", { cx: ellipse.cx, cy: ellipse.cy, rx: ellipse.rx, ry: ellipse.ry, fill: ellipse.fill, opacity: ellipse.opacity }, `e-${scene.uid}-${index}`))), scene.circles.map((circle, index) => (_jsx("circle", { cx: circle.cx, cy: circle.cy, r: circle.r, fill: circle.fill, opacity: circle.opacity }, `c-${scene.uid}-${index}`))), scene.paths.map((path, index) => (_jsx("path", { d: path.d, fill: path.fill, opacity: path.opacity }, `p-${scene.uid}-${index}`))), scene.polygons.map((polygon, index) => (_jsx("polygon", { points: polygon.points, fill: polygon.fill, opacity: polygon.opacity }, `g-${scene.uid}-${index}`)))] }), _jsx("div", { className: "profile-cover-grain pointer-events-none absolute inset-0" })] }));
|
|
12
|
+
}
|
|
13
|
+
/** @deprecated Use CoverPattern — kept as the journalD name. */
|
|
14
|
+
export const ProfileCoverPattern = CoverPattern;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type DataTableToolbarProps = {
|
|
3
|
+
query?: string;
|
|
4
|
+
onQueryChange?: (value: string) => void;
|
|
5
|
+
searchPlaceholder?: string;
|
|
6
|
+
filters?: ReactNode;
|
|
7
|
+
actions?: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
hideSearch?: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** Search + filter slot + actions row above data tables. */
|
|
12
|
+
export declare function DataTableToolbar({ query, onQueryChange, searchPlaceholder, filters, actions, className, hideSearch, }: DataTableToolbarProps): import("react").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=DataTableToolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTableToolbar.d.ts","sourceRoot":"","sources":["../../src/composites/DataTableToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,EAC/B,KAAU,EACV,aAAa,EACb,iBAA6B,EAC7B,OAAO,EACP,OAAO,EACP,SAAS,EACT,UAAU,GACX,EAAE,qBAAqB,+BAwBvB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
import { SearchField } from "./SearchField";
|
|
4
|
+
/** Search + filter slot + actions row above data tables. */
|
|
5
|
+
export function DataTableToolbar({ query = "", onQueryChange, searchPlaceholder = "Search…", filters, actions, className, hideSearch, }) {
|
|
6
|
+
return (_jsxs("div", { "data-slot": "data-table-toolbar", className: cn("flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", className), children: [_jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2 sm:flex-row sm:items-center", children: [!hideSearch && onQueryChange ? (_jsx(SearchField, { value: query, onChange: (e) => onQueryChange(e.target.value), placeholder: searchPlaceholder, containerClassName: "w-full sm:max-w-xs", className: "h-10 rounded-xl" })) : null, filters ? _jsx("div", { className: "flex flex-wrap items-center gap-2", children: filters }) : null] }), actions ? _jsx("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null] }));
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DividerLabel.d.ts","sourceRoot":"","sources":["../../src/composites/DividerLabel.tsx"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,SAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAaA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
export function DividerLabel({ label, className, }) {
|
|
4
|
+
return (_jsxs("div", { "data-slot": "divider-label", className: cn("flex items-center gap-3", className), children: [_jsx("div", { className: "h-px flex-1 bg-border/60" }), _jsx("span", { className: "text-[10px] font-black uppercase tracking-widest text-muted-foreground", children: label }), _jsx("div", { className: "h-px flex-1 bg-border/60" })] }));
|
|
5
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LucideIcon } from "lucide-react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export type EmptyStateProps = {
|
|
4
|
+
icon?: LucideIcon;
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
actionLabel?: string;
|
|
8
|
+
onAction?: () => void;
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
className?: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Empty / zero-state panel for lists and dashboards.
|
|
14
|
+
*/
|
|
15
|
+
export declare function EmptyState({ icon: Icon, title, description, actionLabel, onAction, children, className, }: EmptyStateProps): import("react").JSX.Element;
|
|
16
|
+
//# sourceMappingURL=EmptyState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmptyState.d.ts","sourceRoot":"","sources":["../../src/composites/EmptyState.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EAAE,IAAI,EACV,KAAK,EACL,WAAW,EACX,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,SAAS,GACV,EAAE,eAAe,+BA2BjB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
import { Button } from "../primitives/Button";
|
|
4
|
+
import { GlassCard } from "./GlassCard";
|
|
5
|
+
/**
|
|
6
|
+
* Empty / zero-state panel for lists and dashboards.
|
|
7
|
+
*/
|
|
8
|
+
export function EmptyState({ icon: Icon, title, description, actionLabel, onAction, children, className, }) {
|
|
9
|
+
return (_jsxs(GlassCard, { variant: "subtle", padding: "lg", "data-slot": "empty-state", className: cn("flex flex-col items-center text-center", className), children: [Icon ? (_jsx("div", { className: "mb-4 rounded-2xl border border-border/40 bg-background/50 p-3 text-muted-foreground", children: _jsx(Icon, { className: "h-6 w-6" }) })) : null, _jsx("h3", { className: "text-base font-black tracking-tight text-foreground", children: title }), description ? (_jsx("p", { className: "mt-1.5 max-w-sm text-sm font-medium text-muted-foreground", children: description })) : null, actionLabel && onAction ? (_jsx(Button, { className: "mt-4", onClick: onAction, children: actionLabel })) : null, children] }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EntityCard — quiet glass list-row / tile baseline.
|
|
3
|
+
*
|
|
4
|
+
* Use for directory rows, trash items, and other entity summaries that need
|
|
5
|
+
* consistent glass surface, radius, and padding without feature-specific chrome.
|
|
6
|
+
*/
|
|
7
|
+
import type { HTMLAttributes } from "react";
|
|
8
|
+
type EntityCardElement = "div" | "li" | "article" | "section" | "button" | "a";
|
|
9
|
+
export type EntityCardProps = HTMLAttributes<HTMLElement> & {
|
|
10
|
+
/** Rendered HTML element. Defaults to `div`. */
|
|
11
|
+
as?: EntityCardElement;
|
|
12
|
+
/** Slightly denser padding for compact lists. */
|
|
13
|
+
density?: "default" | "compact";
|
|
14
|
+
/** Soft hover lift for interactive rows (navigation / selection). */
|
|
15
|
+
interactive?: boolean;
|
|
16
|
+
href?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Glass surface wrapper for entity list items.
|
|
20
|
+
*/
|
|
21
|
+
export declare function EntityCard({ as, density, interactive, className, children, href, ...rest }: EntityCardProps): import("react").JSX.Element;
|
|
22
|
+
export type EntityCardTitleProps = HTMLAttributes<HTMLParagraphElement>;
|
|
23
|
+
/** Primary title inside an EntityCard. */
|
|
24
|
+
export declare function EntityCardTitle({ className, ...props }: EntityCardTitleProps): import("react").JSX.Element;
|
|
25
|
+
export type EntityCardMetaProps = HTMLAttributes<HTMLParagraphElement>;
|
|
26
|
+
/** Secondary / muted line under the title. */
|
|
27
|
+
export declare function EntityCardMeta({ className, ...props }: EntityCardMetaProps): import("react").JSX.Element;
|
|
28
|
+
/** Compact type / status chip for entity cards. */
|
|
29
|
+
export declare function EntityCardChip({ className, ...props }: HTMLAttributes<HTMLSpanElement>): import("react").JSX.Element;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=EntityCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityCard.d.ts","sourceRoot":"","sources":["../../src/composites/EntityCard.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,OAAO,CAAC;AAGzD,KAAK,iBAAiB,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,GAAG,CAAC;AAE/E,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,WAAW,CAAC,GAAG;IAC1D,gDAAgD;IAChD,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB,iDAAiD;IACjD,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,qEAAqE;IACrE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,CAAC,EACzB,EAAE,EACF,OAAmB,EACnB,WAAmB,EACnB,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,GAAG,IAAI,EACR,EAAE,eAAe,+BAkBjB;AAED,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;AAExE,0CAA0C;AAC1C,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,+BAW5E;AAED,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;AAEvE,8CAA8C;AAC9C,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,+BAW1E;AAED,mDAAmD;AACnD,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,eAAe,CAAC,+BAWjC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
/**
|
|
4
|
+
* Glass surface wrapper for entity list items.
|
|
5
|
+
*/
|
|
6
|
+
export function EntityCard({ as, density = "default", interactive = false, className, children, href, ...rest }) {
|
|
7
|
+
const Component = (as ?? (href ? "a" : "div"));
|
|
8
|
+
return (_jsx(Component, { ...(href ? { href } : {}), "data-slot": "entity-card", className: cn("entity-card", density === "compact" && "entity-card-compact", interactive && "entity-card-interactive", className), ...rest, children: children }));
|
|
9
|
+
}
|
|
10
|
+
/** Primary title inside an EntityCard. */
|
|
11
|
+
export function EntityCardTitle({ className, ...props }) {
|
|
12
|
+
return (_jsx("p", { "data-slot": "entity-card-title", className: cn("truncate text-sm font-semibold text-foreground sm:text-[15px]", className), ...props }));
|
|
13
|
+
}
|
|
14
|
+
/** Secondary / muted line under the title. */
|
|
15
|
+
export function EntityCardMeta({ className, ...props }) {
|
|
16
|
+
return (_jsx("p", { "data-slot": "entity-card-meta", className: cn("mt-0.5 line-clamp-2 text-xs text-muted-foreground sm:text-[13px]", className), ...props }));
|
|
17
|
+
}
|
|
18
|
+
/** Compact type / status chip for entity cards. */
|
|
19
|
+
export function EntityCardChip({ className, ...props }) {
|
|
20
|
+
return (_jsx("span", { "data-slot": "entity-card-chip", className: cn("inline-flex shrink-0 rounded-full border border-border/50 bg-muted/40 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wider text-muted-foreground", className), ...props }));
|
|
21
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type EntityMediaCardProps = {
|
|
3
|
+
title: string;
|
|
4
|
+
subtitle?: string;
|
|
5
|
+
statusLine?: string;
|
|
6
|
+
imageUrl?: string;
|
|
7
|
+
hideImage?: boolean;
|
|
8
|
+
/** Initials when no image */
|
|
9
|
+
fallbackLabel?: string;
|
|
10
|
+
tags?: ReactNode;
|
|
11
|
+
overlays?: ReactNode;
|
|
12
|
+
menu?: ReactNode;
|
|
13
|
+
meta?: ReactNode;
|
|
14
|
+
href?: string;
|
|
15
|
+
onClick?: () => void;
|
|
16
|
+
size?: "large" | "small" | "compact";
|
|
17
|
+
orientation?: "stack" | "row";
|
|
18
|
+
className?: string;
|
|
19
|
+
imageClassName?: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Entity card with photo (or initials fallback) — contact / directory style.
|
|
23
|
+
*/
|
|
24
|
+
export declare function EntityMediaCard({ title, subtitle, statusLine, imageUrl, hideImage, fallbackLabel, tags, overlays, menu, meta, href, onClick, size, orientation, className, imageClassName, }: EntityMediaCardProps): import("react").JSX.Element;
|
|
25
|
+
//# sourceMappingURL=EntityMediaCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityMediaCard.d.ts","sourceRoot":"","sources":["../../src/composites/EntityMediaCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6BAA6B;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IACrC,WAAW,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,aAAa,EACb,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,IAAc,EACd,WAAqB,EACrB,SAAS,EACT,cAAc,GACf,EAAE,oBAAoB,+BA0EtB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/cn";
|
|
3
|
+
/**
|
|
4
|
+
* Entity card with photo (or initials fallback) — contact / directory style.
|
|
5
|
+
*/
|
|
6
|
+
export function EntityMediaCard({ title, subtitle, statusLine, imageUrl, hideImage, fallbackLabel, tags, overlays, menu, meta, href, onClick, size = "large", orientation = "stack", className, imageClassName, }) {
|
|
7
|
+
const Comp = href ? "a" : onClick ? "button" : "div";
|
|
8
|
+
const initials = fallbackLabel ||
|
|
9
|
+
title
|
|
10
|
+
.split(/\s+/)
|
|
11
|
+
.slice(0, 2)
|
|
12
|
+
.map((w) => w[0]?.toUpperCase() ?? "")
|
|
13
|
+
.join("") ||
|
|
14
|
+
"?";
|
|
15
|
+
const photoAspect = size === "compact" ? "aspect-square" : size === "small" ? "aspect-[4/3]" : "aspect-square";
|
|
16
|
+
return (_jsxs(Comp, { href: href, type: onClick && !href ? "button" : undefined, onClick: onClick, "data-slot": "entity-media-card", className: cn("group flex overflow-hidden rounded-2xl border border-white/45 bg-card text-left shadow-[0_8px_30px_rgb(0,0,0,0.04)] transition-[transform,border-color] duration-200 dark:border-white/12", "hover:-translate-y-0.5 hover:border-primary/15", orientation === "row" ? "flex-row" : "flex-col", className), children: [_jsxs("div", { className: cn("relative shrink-0 overflow-hidden bg-muted", orientation === "row" ? "w-[42%] min-w-[7rem]" : "w-full", orientation === "stack" && photoAspect, imageClassName), children: [!hideImage && imageUrl ? (_jsx("img", { src: imageUrl, alt: "", className: "size-full object-cover transition-transform duration-700 group-hover:scale-110" })) : (_jsx("div", { className: "flex size-full items-center justify-center bg-gradient-to-br from-primary/20 via-muted to-accent-highlight/20 text-2xl font-black text-primary", children: initials })), overlays ? _jsx("div", { className: "absolute inset-0 p-2", children: overlays }) : null] }), _jsxs("div", { className: cn("relative flex min-w-0 flex-1 flex-col bg-white dark:bg-card", size === "compact" ? "gap-1 p-2.5" : "gap-1.5 p-3 sm:p-4"), children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "truncate font-bold tracking-tight group-hover:text-primary", children: title }), subtitle ? (_jsx("p", { className: "truncate text-xs font-medium text-muted-foreground", children: subtitle })) : null, statusLine ? (_jsx("p", { className: "mt-0.5 text-[9px] font-bold uppercase tracking-widest text-muted-foreground/80", children: statusLine })) : null] }), menu] }), meta, tags ? _jsx("div", { className: "mt-auto flex flex-wrap gap-1 pt-1", children: tags }) : null] })] }));
|
|
17
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FilterSheet — shared filter chrome for floating page toolbars.
|
|
3
|
+
*
|
|
4
|
+
* Popover on desktop / tablet, bottom drawer on small screens.
|
|
5
|
+
* Feature pages supply trigger + body content; this shell owns layout,
|
|
6
|
+
* clear/close, and the mobile Done footer.
|
|
7
|
+
*/
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
export type FilterSheetProps = {
|
|
10
|
+
open: boolean;
|
|
11
|
+
onOpenChange: (open: boolean) => void;
|
|
12
|
+
/** Desktop / `md+` control — typically a `Button` using `floatingPageChromePillClass`. */
|
|
13
|
+
trigger: React.ReactElement<{
|
|
14
|
+
onClick?: React.MouseEventHandler;
|
|
15
|
+
}>;
|
|
16
|
+
/** Optional compact control for small screens; defaults to `trigger` if omitted. */
|
|
17
|
+
mobileTrigger?: React.ReactElement<{
|
|
18
|
+
onClick?: React.MouseEventHandler;
|
|
19
|
+
}>;
|
|
20
|
+
title: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
hasActiveFilters?: boolean;
|
|
23
|
+
onClear?: () => void;
|
|
24
|
+
clearLabel?: string;
|
|
25
|
+
doneLabel?: string;
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
contentClassName?: string;
|
|
28
|
+
popoverClassName?: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Responsive filter panel used by directory, history, and similar list pages.
|
|
32
|
+
*/
|
|
33
|
+
export declare function FilterSheet({ open, onOpenChange, trigger, mobileTrigger, title, description, hasActiveFilters, onClear, clearLabel, doneLabel, children, contentClassName, popoverClassName, }: FilterSheetProps): React.JSX.Element;
|
|
34
|
+
//# sourceMappingURL=FilterSheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterSheet.d.ts","sourceRoot":"","sources":["../../src/composites/FilterSheet.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAmB/B,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,0FAA0F;IAC1F,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC;QAAE,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAA;KAAE,CAAC,CAAC;IACnE,oFAAoF;IACpF,aAAa,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;QAAE,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAA;KAAE,CAAC,CAAC;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAcF;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,aAAa,EACb,KAAK,EACL,WAAW,EACX,gBAAwB,EACxB,OAAO,EACP,UAAoB,EACpB,SAAkB,EAClB,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,GACjB,EAAE,gBAAgB,qBAwGlB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* FilterSheet — shared filter chrome for floating page toolbars.
|
|
4
|
+
*
|
|
5
|
+
* Popover on desktop / tablet, bottom drawer on small screens.
|
|
6
|
+
* Feature pages supply trigger + body content; this shell owns layout,
|
|
7
|
+
* clear/close, and the mobile Done footer.
|
|
8
|
+
*/
|
|
9
|
+
import * as React from "react";
|
|
10
|
+
import { X } from "lucide-react";
|
|
11
|
+
import { cn } from "../lib/cn";
|
|
12
|
+
import { useIsMobile } from "../lib/use-media-query";
|
|
13
|
+
import { Button } from "../primitives/Button";
|
|
14
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../primitives/Popover";
|
|
15
|
+
import { Drawer, DrawerContent, DrawerDescription, DrawerHeader, DrawerTitle, } from "./BottomSheet";
|
|
16
|
+
import { ChromeAttachedCaret, FLOATING_PAGE_CHROME_POPOVER_OFFSET, floatingPageChromeAttachedPopoverClass, } from "./FloatingPageChrome";
|
|
17
|
+
function mergeMobileTriggerClick(trigger, openDrawer) {
|
|
18
|
+
return React.cloneElement(trigger, {
|
|
19
|
+
onClick: (e) => {
|
|
20
|
+
trigger.props.onClick?.(e);
|
|
21
|
+
openDrawer();
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Responsive filter panel used by directory, history, and similar list pages.
|
|
27
|
+
*/
|
|
28
|
+
export function FilterSheet({ open, onOpenChange, trigger, mobileTrigger, title, description, hasActiveFilters = false, onClear, clearLabel = "Clear", doneLabel = "Done", children, contentClassName, popoverClassName, }) {
|
|
29
|
+
const isMobile = useIsMobile();
|
|
30
|
+
const mobileControl = mobileTrigger ?? trigger;
|
|
31
|
+
const clearControl = hasActiveFilters && onClear ? (_jsxs("button", { type: "button", onClick: onClear, className: "flex items-center gap-1 rounded-lg px-2 py-1 text-muted-foreground/80 transition-colors hover:bg-muted/50 hover:text-foreground", children: [_jsx(X, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider", children: clearLabel })] })) : null;
|
|
32
|
+
if (isMobile) {
|
|
33
|
+
return (_jsxs(_Fragment, { children: [mergeMobileTriggerClick(mobileControl, () => onOpenChange(true)), _jsx(Drawer, { open: open, onOpenChange: onOpenChange, children: _jsxs(DrawerContent, { className: cn("glass-panel max-h-[92vh] rounded-t-2xl border-border/60 bg-background/90 pb-0 backdrop-blur-xl sm:hidden", contentClassName), children: [_jsxs(DrawerHeader, { className: "flex flex-row items-start justify-between gap-3 space-y-0 border-b border-border/40 px-4 pb-3 pt-2 text-left", children: [_jsxs("div", { className: "min-w-0 space-y-1 pr-8", children: [_jsx(DrawerTitle, { className: "text-base font-bold tracking-tight text-foreground", children: title }), description ? (_jsx(DrawerDescription, { className: "text-xs text-muted-foreground", children: description })) : null] }), _jsx("div", { className: "flex shrink-0 items-center gap-1", children: clearControl })] }), _jsx("div", { className: "max-h-[min(65vh,32rem)] overflow-y-auto px-0", children: _jsx("div", { className: "flex flex-col gap-3 p-3 pt-1", children: children }) }), _jsx("div", { className: "flex justify-end gap-2 border-t border-border/40 p-4 pb-[calc(1rem+env(safe-area-inset-bottom))]", children: _jsx(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), className: "h-9 rounded-xl px-4 text-xs font-semibold uppercase tracking-wider", children: doneLabel }) })] }) })] }));
|
|
34
|
+
}
|
|
35
|
+
return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: trigger }), _jsxs(PopoverContent, { align: "end", side: "bottom", sideOffset: FLOATING_PAGE_CHROME_POPOVER_OFFSET, className: cn(floatingPageChromeAttachedPopoverClass, "w-[min(calc(100vw-1rem),24rem)]", popoverClassName, contentClassName), onOpenAutoFocus: (e) => e.preventDefault(), children: [_jsx(ChromeAttachedCaret, { align: "end" }), _jsx("div", { className: "border-b border-border/40 px-3 py-2.5 text-left", children: _jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0 pr-2", children: [_jsx("p", { className: "text-sm font-bold tracking-tight text-foreground", children: title }), description ? (_jsx("p", { className: "text-xs text-muted-foreground", children: description })) : null] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [clearControl, _jsx("button", { type: "button", onClick: () => onOpenChange(false), className: "flex h-7 w-7 items-center justify-center rounded-lg text-muted-foreground/60 transition-colors hover:bg-muted/50 hover:text-foreground", "aria-label": "Close", children: _jsx(X, { className: "h-4 w-4" }) })] })] }) }), _jsx("div", { className: "flex max-h-[min(70vh,28rem)] flex-col gap-3 overflow-y-auto p-3", children: children })] })] }));
|
|
36
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Floating page chrome — Apple liquid-glass toolbar under the app nav.
|
|
3
|
+
*
|
|
4
|
+
* Back and the page title share an identity control; search, filters, and
|
|
5
|
+
* actions sit on the same frosted tray. Pair with `app-page-chrome` (or pass
|
|
6
|
+
* `children` to `FloatingPageChromeBar`) so page content scrolls below the
|
|
7
|
+
* bar instead of under it.
|
|
8
|
+
*/
|
|
9
|
+
import type { ReactNode, Ref } from "react";
|
|
10
|
+
/** Shared control height for the sticky chrome row. */
|
|
11
|
+
export declare const FLOATING_PAGE_CHROME_HEIGHT_CLASS = "h-9";
|
|
12
|
+
/**
|
|
13
|
+
* Pinned rail below the fixed app chrome. Not sticky — pair with
|
|
14
|
+
* `app-page-chrome` so page content scrolls in `.app-page-chrome-body`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const floatingPageChromeShellClass = "shrink-0 app-frame-pad pt-2 pb-1.5";
|
|
17
|
+
/** Inner Apple glass capsule that holds identity, search, and actions. */
|
|
18
|
+
export declare const floatingPageChromeTrayClass = "glass-page-toolbar flex w-full min-w-0 flex-col gap-2 px-1.5 py-1 sm:px-2";
|
|
19
|
+
/** Combined back + page name — flat on the glass tray. */
|
|
20
|
+
export declare const floatingPageChromeIdentityClass = "flex h-9 min-w-0 shrink items-center rounded-full";
|
|
21
|
+
/** Search field as an inset pill on the glass tray. */
|
|
22
|
+
export declare const floatingPageChromeSearchWrapClass: string;
|
|
23
|
+
export declare const floatingPageChromeSearchInputClass = "h-9 w-full rounded-full border-0 bg-transparent py-0 pl-9 pr-8 text-sm leading-none shadow-none focus-visible:ring-0";
|
|
24
|
+
/** View & filters / sort — inset on the glass tray, same height as search. */
|
|
25
|
+
export declare const floatingPageChromePillClass: string;
|
|
26
|
+
/** Icon-only control (mobile search, mobile sort). */
|
|
27
|
+
export declare const floatingPageChromeIconPillClass: string;
|
|
28
|
+
/** Cluster of related icon actions (add / layout / more). */
|
|
29
|
+
export declare const floatingPageChromeClusterClass: string;
|
|
30
|
+
/** App-bar utility island (settings + notifications). */
|
|
31
|
+
export declare const appChromeActionClusterClass: string;
|
|
32
|
+
/** Primary CTA in the chrome row. */
|
|
33
|
+
export declare const floatingPageChromePrimaryClass = "h-9 gap-1.5 rounded-full px-3 text-xs font-semibold shadow-lg";
|
|
34
|
+
/** Gap between a trigger pill and its attached menu (leaves room for the caret). */
|
|
35
|
+
export declare const FLOATING_PAGE_CHROME_POPOVER_OFFSET = 10;
|
|
36
|
+
export declare const floatingPageChromeAttachedPopoverClass = "overflow-visible rounded-2xl border border-border/50 bg-card/95 p-0 shadow-[0_16px_40px_-18px_rgba(15,23,42,0.42)] backdrop-blur-xl dark:border-white/10 dark:bg-zinc-900/92";
|
|
37
|
+
/** Inner buttons sitting inside a glass cluster (no second chip). */
|
|
38
|
+
export declare const appChromeClusterButtonClass = "relative z-[70] h-8 w-8 shrink-0 rounded-full px-0 text-muted-foreground transition-colors hover:bg-muted/70 hover:text-foreground data-[state=open]:bg-muted/80 data-[state=open]:text-foreground";
|
|
39
|
+
/**
|
|
40
|
+
* Small pointer that visually joins a popover to its trigger.
|
|
41
|
+
* `align="end"` matches popover `align="end"` (caret sits under the right-hand control).
|
|
42
|
+
*/
|
|
43
|
+
export declare function ChromeAttachedCaret({ align, }: {
|
|
44
|
+
align?: "start" | "end";
|
|
45
|
+
}): import("react").JSX.Element;
|
|
46
|
+
export type FloatingPageChromeIdentityProps = {
|
|
47
|
+
onBack?: () => void;
|
|
48
|
+
title: ReactNode;
|
|
49
|
+
count?: ReactNode;
|
|
50
|
+
/** Spoken name for the count badge, e.g. "253 people". */
|
|
51
|
+
countLabel?: string;
|
|
52
|
+
backLabel?: string;
|
|
53
|
+
className?: string;
|
|
54
|
+
};
|
|
55
|
+
export declare function FloatingPageChromeIdentity({ onBack, title, count, countLabel, backLabel, className, }: FloatingPageChromeIdentityProps): import("react").JSX.Element;
|
|
56
|
+
export type FloatingPageChromeSearchFieldProps = {
|
|
57
|
+
value: string;
|
|
58
|
+
onChange: (value: string) => void;
|
|
59
|
+
onClear?: () => void;
|
|
60
|
+
placeholder: string;
|
|
61
|
+
inputRef?: Ref<HTMLInputElement>;
|
|
62
|
+
className?: string;
|
|
63
|
+
fullWidth?: boolean;
|
|
64
|
+
type?: "search" | "text";
|
|
65
|
+
"aria-label"?: string;
|
|
66
|
+
};
|
|
67
|
+
/** Search pill used in the chrome row and the mobile reveal row. */
|
|
68
|
+
export declare function FloatingPageChromeSearchField({ value, onChange, onClear, placeholder, inputRef, className, fullWidth, type, "aria-label": ariaLabel, }: FloatingPageChromeSearchFieldProps): import("react").JSX.Element;
|
|
69
|
+
export type FloatingPageChromeBarProps = {
|
|
70
|
+
identity: ReactNode;
|
|
71
|
+
search?: ReactNode;
|
|
72
|
+
actions?: ReactNode;
|
|
73
|
+
below?: ReactNode;
|
|
74
|
+
/** Page body — scrolls independently so it cannot pass under the toolbar. */
|
|
75
|
+
children?: ReactNode;
|
|
76
|
+
className?: string;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Shared chrome row: identity, optional centered search, trailing actions.
|
|
80
|
+
* `below` is a second row (mobile search, compact TOC) and is not itself a full-bleed bar.
|
|
81
|
+
* Pass `children` to pin this bar above a nested scroller (content never slides under it).
|
|
82
|
+
*/
|
|
83
|
+
export declare function FloatingPageChromeBar({ identity, search, actions, below, children, className, }: FloatingPageChromeBarProps): import("react").JSX.Element;
|
|
84
|
+
/** Shell + glass tray for pages that compose the chrome row by hand. */
|
|
85
|
+
export declare function FloatingPageChromeShell({ children, below, className, }: {
|
|
86
|
+
children: ReactNode;
|
|
87
|
+
below?: ReactNode;
|
|
88
|
+
className?: string;
|
|
89
|
+
}): import("react").JSX.Element;
|
|
90
|
+
//# sourceMappingURL=FloatingPageChrome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FloatingPageChrome.d.ts","sourceRoot":"","sources":["../../src/composites/FloatingPageChrome.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAK5C,uDAAuD;AACvD,eAAO,MAAM,iCAAiC,QAAQ,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,4BAA4B,uCACH,CAAC;AAEvC,0EAA0E;AAC1E,eAAO,MAAM,2BAA2B,8EACqC,CAAC;AAU9E,0DAA0D;AAC1D,eAAO,MAAM,+BAA+B,sDACS,CAAC;AAEtD,uDAAuD;AACvD,eAAO,MAAM,iCAAiC,QAG7C,CAAC;AAEF,eAAO,MAAM,kCAAkC,yHACyE,CAAC;AAEzH,8EAA8E;AAC9E,eAAO,MAAM,2BAA2B,QAGvC,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,+BAA+B,QAG3C,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,8BAA8B,QAG1C,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,2BAA2B,QAGvC,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,8BAA8B,kEACsB,CAAC;AAElE,oFAAoF;AACpF,eAAO,MAAM,mCAAmC,KAAK,CAAC;AAEtD,eAAO,MAAM,sCAAsC,iLAC6H,CAAC;AAEjL,qEAAqE;AACrE,eAAO,MAAM,2BAA2B,uMAC8J,CAAC;AAEvM;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,KAAa,GACd,EAAE;IACD,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;CACzB,+BAUA;AAED,MAAM,MAAM,+BAA+B,GAAG;IAC5C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,EACzC,MAAM,EACN,KAAK,EACL,KAAK,EACL,UAAU,EACV,SAAqB,EACrB,SAAS,GACV,EAAE,+BAA+B,+BAmCjC;AAED,MAAM,MAAM,kCAAkC,GAAG;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,oEAAoE;AACpE,wBAAgB,6BAA6B,CAAC,EAC5C,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAW,EACX,QAAQ,EACR,SAAS,EACT,SAAiB,EACjB,IAAe,EACf,YAAY,EAAE,SAAS,GACxB,EAAE,kCAAkC,+BA8BpC;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,MAAM,EACN,OAAO,EACP,KAAK,EACL,QAAQ,EACR,SAAS,GACV,EAAE,0BAA0B,+BAoC5B;AAED,wEAAwE;AACxE,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,KAAK,EACL,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BASA"}
|