@nanisoft/prism-ui 0.10.1 → 0.13.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/LICENSE +21 -21
- package/dist/.tsbuildinfo +1 -1
- package/dist/blocks/app-shell-01/app-shell.js +4 -4
- package/dist/blocks/app-shell-01/index.d.ts +2 -2
- package/dist/blocks/app-shell-01/index.js +1 -1
- package/dist/blocks/auth-form-01/auth-form.d.ts +11 -1
- package/dist/blocks/auth-form-01/auth-form.d.ts.map +1 -1
- package/dist/blocks/auth-form-01/auth-form.js +11 -8
- package/dist/blocks/auth-form-01/index.d.ts +2 -2
- package/dist/blocks/auth-form-01/index.js +1 -1
- package/dist/blocks/cta-01/cta.d.ts +26 -21
- package/dist/blocks/cta-01/cta.d.ts.map +1 -1
- package/dist/blocks/cta-01/cta.js +2 -2
- package/dist/blocks/cta-01/index.d.ts +2 -2
- package/dist/blocks/cta-01/index.js +1 -1
- package/dist/blocks/data-table-01/data-table.js +7 -7
- package/dist/blocks/data-table-01/index.d.ts +2 -2
- package/dist/blocks/data-table-01/index.js +1 -1
- package/dist/blocks/empty-state-01/empty-state.d.ts +143 -0
- package/dist/blocks/empty-state-01/empty-state.d.ts.map +1 -0
- package/dist/blocks/empty-state-01/empty-state.js +104 -0
- package/dist/blocks/empty-state-01/index.d.ts +3 -0
- package/dist/blocks/empty-state-01/index.d.ts.map +1 -0
- package/dist/blocks/empty-state-01/index.js +1 -0
- package/dist/blocks/feature-grid-01/feature-grid.d.ts +28 -1
- package/dist/blocks/feature-grid-01/feature-grid.d.ts.map +1 -1
- package/dist/blocks/feature-grid-01/feature-grid.js +34 -3
- package/dist/blocks/feature-grid-01/index.d.ts +2 -2
- package/dist/blocks/feature-grid-01/index.js +1 -1
- package/dist/blocks/hero-01/hero.d.ts +49 -17
- package/dist/blocks/hero-01/hero.d.ts.map +1 -1
- package/dist/blocks/hero-01/hero.js +14 -9
- package/dist/blocks/hero-01/index.d.ts +2 -1
- package/dist/blocks/hero-01/index.d.ts.map +1 -1
- package/dist/blocks/hero-01/index.js +1 -1
- package/dist/blocks/index.d.ts +20 -20
- package/dist/blocks/index.js +19 -19
- package/dist/blocks/instrument-panel-01/index.d.ts +2 -2
- package/dist/blocks/instrument-panel-01/index.js +1 -1
- package/dist/blocks/instrument-panel-01/instrument-panel.js +1 -1
- package/dist/blocks/logo-strip-01/index.d.ts +2 -2
- package/dist/blocks/logo-strip-01/index.js +1 -1
- package/dist/blocks/logo-strip-01/logo-strip.d.ts +1 -1
- package/dist/blocks/logo-strip-01/logo-strip.js +2 -2
- package/dist/blocks/note-grid-01/index.d.ts +2 -2
- package/dist/blocks/note-grid-01/index.js +1 -1
- package/dist/blocks/note-grid-01/note-grid.d.ts +1 -1
- package/dist/blocks/note-grid-01/note-grid.js +1 -1
- package/dist/blocks/page-header-01/index.d.ts +2 -2
- package/dist/blocks/page-header-01/index.js +1 -1
- package/dist/blocks/page-header-01/page-header.d.ts +1 -1
- package/dist/blocks/page-header-01/page-header.js +4 -4
- package/dist/blocks/pricing-01/index.d.ts +1 -1
- package/dist/blocks/pricing-01/index.js +1 -1
- package/dist/blocks/pricing-01/pricing.d.ts +8 -1
- package/dist/blocks/pricing-01/pricing.d.ts.map +1 -1
- package/dist/blocks/pricing-01/pricing.js +15 -5
- package/dist/blocks/process-flow-01/index.d.ts +3 -0
- package/dist/blocks/process-flow-01/index.d.ts.map +1 -0
- package/dist/blocks/process-flow-01/index.js +1 -0
- package/dist/blocks/process-flow-01/process-flow.d.ts +118 -0
- package/dist/blocks/process-flow-01/process-flow.d.ts.map +1 -0
- package/dist/blocks/process-flow-01/process-flow.js +71 -0
- package/dist/blocks/process-rail-01/index.d.ts +2 -2
- package/dist/blocks/process-rail-01/index.js +1 -1
- package/dist/blocks/process-rail-01/process-rail.d.ts +1 -1
- package/dist/blocks/process-rail-01/process-rail.js +2 -2
- package/dist/blocks/product-grid-01/index.d.ts +2 -2
- package/dist/blocks/product-grid-01/index.js +1 -1
- package/dist/blocks/product-grid-01/product-grid.d.ts +37 -5
- package/dist/blocks/product-grid-01/product-grid.d.ts.map +1 -1
- package/dist/blocks/product-grid-01/product-grid.js +20 -6
- package/dist/blocks/run-console-01/index.d.ts +3 -0
- package/dist/blocks/run-console-01/index.d.ts.map +1 -0
- package/dist/blocks/run-console-01/index.js +1 -0
- package/dist/blocks/run-console-01/run-console.d.ts +111 -0
- package/dist/blocks/run-console-01/run-console.d.ts.map +1 -0
- package/dist/blocks/run-console-01/run-console.js +48 -0
- package/dist/blocks/settings-panel-01/index.d.ts +2 -2
- package/dist/blocks/settings-panel-01/index.js +1 -1
- package/dist/blocks/settings-panel-01/settings-panel.d.ts +11 -1
- package/dist/blocks/settings-panel-01/settings-panel.d.ts.map +1 -1
- package/dist/blocks/settings-panel-01/settings-panel.js +15 -10
- package/dist/blocks/site-footer/index.d.ts +2 -2
- package/dist/blocks/site-footer/index.js +1 -1
- package/dist/blocks/site-footer/site-footer.d.ts +1 -1
- package/dist/blocks/site-footer/site-footer.js +2 -2
- package/dist/blocks/site-header/index.d.ts +2 -2
- package/dist/blocks/site-header/index.js +1 -1
- package/dist/blocks/site-header/site-header.d.ts +2 -2
- package/dist/blocks/site-header/site-header.js +3 -3
- package/dist/blocks/site-navbar/index.d.ts +3 -0
- package/dist/blocks/site-navbar/index.d.ts.map +1 -0
- package/dist/blocks/site-navbar/index.js +1 -0
- package/dist/blocks/site-navbar/mobile-nav.d.ts +48 -0
- package/dist/blocks/site-navbar/mobile-nav.d.ts.map +1 -0
- package/dist/blocks/site-navbar/mobile-nav.js +35 -0
- package/dist/blocks/site-navbar/mode-toggle.d.ts +39 -0
- package/dist/blocks/site-navbar/mode-toggle.d.ts.map +1 -0
- package/dist/blocks/site-navbar/mode-toggle.js +39 -0
- package/dist/blocks/site-navbar/navbar-controls.d.ts +79 -0
- package/dist/blocks/site-navbar/navbar-controls.d.ts.map +1 -0
- package/dist/blocks/site-navbar/navbar-controls.js +40 -0
- package/dist/blocks/site-navbar/search-entry.d.ts +29 -0
- package/dist/blocks/site-navbar/search-entry.d.ts.map +1 -0
- package/dist/blocks/site-navbar/search-entry.js +52 -0
- package/dist/blocks/site-navbar/site-navbar.d.ts +212 -0
- package/dist/blocks/site-navbar/site-navbar.d.ts.map +1 -0
- package/dist/blocks/site-navbar/site-navbar.js +61 -0
- package/dist/blocks/site-navbar/sites-menu.d.ts +40 -0
- package/dist/blocks/site-navbar/sites-menu.d.ts.map +1 -0
- package/dist/blocks/site-navbar/sites-menu.js +48 -0
- package/dist/blocks/site-navbar/theme-menu.d.ts +47 -0
- package/dist/blocks/site-navbar/theme-menu.d.ts.map +1 -0
- package/dist/blocks/site-navbar/theme-menu.js +55 -0
- package/dist/blocks/stack-grid-01/index.d.ts +2 -2
- package/dist/blocks/stack-grid-01/index.js +1 -1
- package/dist/blocks/stack-grid-01/stack-grid.d.ts +42 -11
- package/dist/blocks/stack-grid-01/stack-grid.d.ts.map +1 -1
- package/dist/blocks/stack-grid-01/stack-grid.js +15 -7
- package/dist/blocks/stats-01/index.d.ts +9 -1
- package/dist/blocks/stats-01/index.d.ts.map +1 -1
- package/dist/blocks/stats-01/index.js +8 -1
- package/dist/blocks/stats-01/stats.d.ts +1 -1
- package/dist/blocks/stats-01/stats.js +2 -2
- package/dist/blocks/status-ledger-01/index.d.ts +2 -2
- package/dist/blocks/status-ledger-01/index.js +1 -1
- package/dist/blocks/status-ledger-01/status-ledger.d.ts +1 -1
- package/dist/blocks/status-ledger-01/status-ledger.js +2 -2
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +473 -1
- package/dist/components/index.d.ts +104 -66
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +74 -40
- package/dist/components/ui/accordion.js +1 -1
- package/dist/components/ui/alert-dialog.d.ts +119 -0
- package/dist/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/components/ui/alert-dialog.js +82 -0
- package/dist/components/ui/alert.js +1 -1
- package/dist/components/ui/aspect-ratio.d.ts +60 -0
- package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
- package/dist/components/ui/aspect-ratio.js +61 -0
- package/dist/components/ui/avatar.js +1 -1
- package/dist/components/ui/badge.js +1 -1
- package/dist/components/ui/breadcrumb.js +1 -1
- package/dist/components/ui/button-group.d.ts +68 -0
- package/dist/components/ui/button-group.d.ts.map +1 -0
- package/dist/components/ui/button-group.js +54 -0
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/calendar.d.ts +158 -0
- package/dist/components/ui/calendar.d.ts.map +1 -0
- package/dist/components/ui/calendar.js +216 -0
- package/dist/components/ui/card.d.ts +18 -6
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/card.js +23 -8
- package/dist/components/ui/carousel.d.ts +118 -0
- package/dist/components/ui/carousel.d.ts.map +1 -0
- package/dist/components/ui/carousel.js +152 -0
- package/dist/components/ui/chart-frame.d.ts +216 -0
- package/dist/components/ui/chart-frame.d.ts.map +1 -0
- package/dist/components/ui/chart-frame.js +286 -0
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/collapsible.d.ts +97 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/collapsible.js +54 -0
- package/dist/components/ui/combobox.d.ts +141 -0
- package/dist/components/ui/combobox.d.ts.map +1 -0
- package/dist/components/ui/combobox.js +243 -0
- package/dist/components/ui/command-palette.d.ts +106 -0
- package/dist/components/ui/command-palette.d.ts.map +1 -0
- package/dist/components/ui/command-palette.js +176 -0
- package/dist/components/ui/command.d.ts +82 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/command.js +37 -0
- package/dist/components/ui/context-menu.d.ts +151 -0
- package/dist/components/ui/context-menu.d.ts.map +1 -0
- package/dist/components/ui/context-menu.js +97 -0
- package/dist/components/ui/cta-link.js +1 -1
- package/dist/components/ui/date-picker.d.ts +111 -0
- package/dist/components/ui/date-picker.d.ts.map +1 -0
- package/dist/components/ui/date-picker.js +74 -0
- package/dist/components/ui/diagram.d.ts +84 -15
- package/dist/components/ui/diagram.d.ts.map +1 -1
- package/dist/components/ui/diagram.js +77 -7
- package/dist/components/ui/dialog.js +1 -1
- package/dist/components/ui/diff.d.ts +105 -0
- package/dist/components/ui/diff.d.ts.map +1 -0
- package/dist/components/ui/diff.js +113 -0
- package/dist/components/ui/dropdown-menu.d.ts +18 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu.js +1 -1
- package/dist/components/ui/fact-list.js +1 -1
- package/dist/components/ui/field.js +1 -1
- package/dist/components/ui/form.d.ts +151 -0
- package/dist/components/ui/form.d.ts.map +1 -0
- package/dist/components/ui/form.js +73 -0
- package/dist/components/ui/hover-card.d.ts +105 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -0
- package/dist/components/ui/hover-card.js +49 -0
- package/dist/components/ui/input-group.d.ts +99 -0
- package/dist/components/ui/input-group.d.ts.map +1 -0
- package/dist/components/ui/input-group.js +83 -0
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/item.d.ts +113 -0
- package/dist/components/ui/item.d.ts.map +1 -0
- package/dist/components/ui/item.js +61 -0
- package/dist/components/ui/kbd.js +1 -1
- package/dist/components/ui/label.d.ts +58 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/label.js +29 -0
- package/dist/components/ui/live-region.d.ts +9 -0
- package/dist/components/ui/live-region.d.ts.map +1 -1
- package/dist/components/ui/live-region.js +10 -2
- package/dist/components/ui/mark.js +1 -1
- package/dist/components/ui/menubar.d.ts +197 -0
- package/dist/components/ui/menubar.d.ts.map +1 -0
- package/dist/components/ui/menubar.js +109 -0
- package/dist/components/ui/meter.d.ts +121 -0
- package/dist/components/ui/meter.d.ts.map +1 -0
- package/dist/components/ui/meter.js +82 -0
- package/dist/components/ui/native-select.d.ts +72 -0
- package/dist/components/ui/native-select.d.ts.map +1 -0
- package/dist/components/ui/native-select.js +55 -0
- package/dist/components/ui/navigation-menu.d.ts +186 -0
- package/dist/components/ui/navigation-menu.d.ts.map +1 -0
- package/dist/components/ui/navigation-menu.js +94 -0
- package/dist/components/ui/number-field.d.ts +111 -0
- package/dist/components/ui/number-field.d.ts.map +1 -0
- package/dist/components/ui/number-field.js +84 -0
- package/dist/components/ui/one-time-code.d.ts +127 -0
- package/dist/components/ui/one-time-code.d.ts.map +1 -0
- package/dist/components/ui/one-time-code.js +57 -0
- package/dist/components/ui/pagination.js +1 -1
- package/dist/components/ui/popover.js +1 -1
- package/dist/components/ui/product-mark.d.ts +1 -1
- package/dist/components/ui/product-mark.js +1 -1
- package/dist/components/ui/product-switcher.d.ts +1 -1
- package/dist/components/ui/product-switcher.js +2 -2
- package/dist/components/ui/progress.js +1 -1
- package/dist/components/ui/prose.js +1 -1
- package/dist/components/ui/pulse-graph.js +1 -1
- package/dist/components/ui/pulse-series.js +1 -1
- package/dist/components/ui/radio-group.js +1 -1
- package/dist/components/ui/resizable.d.ts +129 -0
- package/dist/components/ui/resizable.d.ts.map +1 -0
- package/dist/components/ui/resizable.js +205 -0
- package/dist/components/ui/scroll-area.d.ts +97 -0
- package/dist/components/ui/scroll-area.d.ts.map +1 -0
- package/dist/components/ui/scroll-area.js +68 -0
- package/dist/components/ui/search-dialog.d.ts +139 -0
- package/dist/components/ui/search-dialog.d.ts.map +1 -0
- package/dist/components/ui/search-dialog.js +178 -0
- package/dist/components/ui/section.d.ts +26 -0
- package/dist/components/ui/section.d.ts.map +1 -1
- package/dist/components/ui/section.js +32 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/separator.js +1 -1
- package/dist/components/ui/sheet.d.ts +103 -0
- package/dist/components/ui/sheet.d.ts.map +1 -0
- package/dist/components/ui/sheet.js +58 -0
- package/dist/components/ui/sidebar.d.ts +228 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -0
- package/dist/components/ui/sidebar.js +172 -0
- package/dist/components/ui/signal-field.js +1 -1
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/slider.js +1 -1
- package/dist/components/ui/spinner.d.ts +79 -0
- package/dist/components/ui/spinner.d.ts.map +1 -0
- package/dist/components/ui/spinner.js +79 -0
- package/dist/components/ui/switch.js +1 -1
- package/dist/components/ui/table-sort.d.ts +97 -0
- package/dist/components/ui/table-sort.d.ts.map +1 -0
- package/dist/components/ui/table-sort.js +102 -0
- package/dist/components/ui/table.js +1 -1
- package/dist/components/ui/tabs.js +1 -1
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/timeline.d.ts +106 -0
- package/dist/components/ui/timeline.d.ts.map +1 -0
- package/dist/components/ui/timeline.js +111 -0
- package/dist/components/ui/toast.d.ts +219 -0
- package/dist/components/ui/toast.d.ts.map +1 -0
- package/dist/components/ui/toast.js +270 -0
- package/dist/components/ui/toggle-group.d.ts +118 -0
- package/dist/components/ui/toggle-group.d.ts.map +1 -0
- package/dist/components/ui/toggle-group.js +194 -0
- package/dist/components/ui/toggle.d.ts +73 -0
- package/dist/components/ui/toggle.d.ts.map +1 -0
- package/dist/components/ui/toggle.js +44 -0
- package/dist/components/ui/tooltip.js +1 -1
- package/dist/components/ui/tree.js +1 -1
- package/dist/components/ui/typography.js +1 -1
- package/dist/fonts/Inter-OFL.txt +93 -93
- package/dist/index.d.ts +72 -70
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +61 -60
- package/dist/lib/rank.d.ts +69 -0
- package/dist/lib/rank.d.ts.map +1 -0
- package/dist/lib/rank.js +77 -0
- package/dist/live/index.d.ts +22 -0
- package/dist/live/index.d.ts.map +1 -0
- package/dist/live/index.js +20 -0
- package/dist/live/run-stream-01/index.d.ts +3 -0
- package/dist/live/run-stream-01/index.d.ts.map +1 -0
- package/dist/live/run-stream-01/index.js +1 -0
- package/dist/live/run-stream-01/run-stream.d.ts +125 -0
- package/dist/live/run-stream-01/run-stream.d.ts.map +1 -0
- package/dist/live/run-stream-01/run-stream.js +111 -0
- package/dist/pages/auth-page/index.d.ts +15 -2
- package/dist/pages/auth-page/index.d.ts.map +1 -1
- package/dist/pages/auth-page/index.js +8 -4
- package/dist/pages/blog-post-page/index.js +5 -5
- package/dist/pages/dashboard-page/index.d.ts +4 -4
- package/dist/pages/dashboard-page/index.js +4 -4
- package/dist/pages/docs-shell/docs-shell.d.ts +37 -4
- package/dist/pages/docs-shell/docs-shell.d.ts.map +1 -1
- package/dist/pages/docs-shell/docs-shell.js +107 -16
- package/dist/pages/docs-shell/index.d.ts +2 -2
- package/dist/pages/docs-shell/index.js +1 -1
- package/dist/pages/index.d.ts +14 -14
- package/dist/pages/index.js +7 -7
- package/dist/pages/marketing-page/index.d.ts +6 -6
- package/dist/pages/marketing-page/index.js +5 -5
- package/dist/pages/not-found-page/index.js +4 -4
- package/dist/pages/settings-page/index.d.ts +3 -3
- package/dist/pages/settings-page/index.js +4 -4
- package/dist/provider/index.d.ts +4 -4
- package/dist/provider/index.js +2 -2
- package/dist/provider/provider.d.ts +1 -1
- package/dist/provider/provider.js +1 -1
- package/dist/provider/theme-script.d.ts +1 -1
- package/dist/provider/theme-script.js +1 -1
- package/dist/styles.css +689 -0
- package/package.json +9 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Fragment } from 'react';
|
|
4
|
-
import { Button } from '../../components/ui/button';
|
|
5
|
-
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from '../../components/ui/card';
|
|
6
|
-
import { Field, FieldDescription, FieldGroup, FieldLabel, } from '../../components/ui/field';
|
|
7
|
-
import { Input } from '../../components/ui/input';
|
|
8
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../components/ui/select';
|
|
9
|
-
import { Separator } from '../../components/ui/separator';
|
|
10
|
-
import { Switch } from '../../components/ui/switch';
|
|
11
|
-
import {
|
|
4
|
+
import { Button } from '../../components/ui/button.js';
|
|
5
|
+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from '../../components/ui/card.js';
|
|
6
|
+
import { Field, FieldDescription, FieldGroup, FieldLabel, } from '../../components/ui/field.js';
|
|
7
|
+
import { Input } from '../../components/ui/input.js';
|
|
8
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../components/ui/select.js';
|
|
9
|
+
import { Separator } from '../../components/ui/separator.js';
|
|
10
|
+
import { Switch } from '../../components/ui/switch.js';
|
|
11
|
+
import { childLevel } from '../../components/ui/section.js';
|
|
12
|
+
import { Textarea } from '../../components/ui/textarea.js';
|
|
12
13
|
function SettingsField({ field }) {
|
|
13
14
|
if (field.kind === 'switch') {
|
|
14
15
|
return (_jsxs(Field, { className: "flex-row items-center justify-between gap-4", children: [_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx(FieldLabel, { htmlFor: field.id, children: field.label }), field.description ? (_jsx(FieldDescription, { children: field.description })) : null] }), _jsx(Switch, { id: field.id, checked: field.checked, defaultChecked: field.defaultChecked, onCheckedChange: field.onCheckedChange, disabled: field.disabled })] }));
|
|
@@ -31,8 +32,12 @@ function SettingsField({ field }) {
|
|
|
31
32
|
* block renders the card, the groups and the footer; it owns no values and no
|
|
32
33
|
* copy, so a consumer wires it to whatever form state or mutation they use.
|
|
33
34
|
*/
|
|
34
|
-
export function SettingsPanel01({ title, description, sections, submitLabel, onSubmit, secondaryAction, footer, }) {
|
|
35
|
+
export function SettingsPanel01({ title, description, sections, submitLabel, onSubmit, secondaryAction, footer, headingLevel = 'h2', }) {
|
|
36
|
+
// The panel title is the one heading the panel renders, and a group inside it is
|
|
37
|
+
// one step below, so the whole outline moves together when the panel does.
|
|
38
|
+
const Title = headingLevel;
|
|
39
|
+
const GroupTitle = childLevel(headingLevel);
|
|
35
40
|
const hasFooter = Boolean(submitLabel || secondaryAction || footer);
|
|
36
|
-
return (_jsx("form", { onSubmit: onSubmit, className: "w-full", children: _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: title }), description ? _jsx(CardDescription, { children: description }) : null] }), _jsx(CardContent, { className: "flex flex-col", children: sections.map((section, index) => (_jsxs(Fragment, { children: [index > 0 ? _jsx(Separator, { className: "my-6" }) : null, _jsxs("section", { className: "flex flex-col gap-4", "aria-labelledby": `${section.id}-heading`, children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(
|
|
41
|
+
return (_jsx("form", { onSubmit: onSubmit, className: "w-full", children: _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: _jsx(Title, { children: title }) }), description ? _jsx(CardDescription, { children: description }) : null] }), _jsx(CardContent, { className: "flex flex-col", children: sections.map((section, index) => (_jsxs(Fragment, { children: [index > 0 ? _jsx(Separator, { className: "my-6" }) : null, _jsxs("section", { className: "flex flex-col gap-4", "aria-labelledby": `${section.id}-heading`, children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(GroupTitle, { id: `${section.id}-heading`, className: "text-lg font-semibold tracking-tight", children: section.title }), section.description ? (_jsx("p", { className: "text-muted-foreground text-sm", children: section.description })) : null] }), _jsx(FieldGroup, { children: section.fields.map((field) => (_jsx(SettingsField, { field: field }, field.id))) })] })] }, section.id))) }), hasFooter ? (_jsxs(CardFooter, { className: "justify-end gap-2", children: [footer, secondaryAction ? (_jsx(Button, { type: "button", variant: "outline", onClick: secondaryAction.onClick, children: secondaryAction.label })) : null, submitLabel ? _jsx(Button, { type: "submit", children: submitLabel }) : null] })) : null] }) }));
|
|
37
42
|
}
|
|
38
43
|
export default SettingsPanel01;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { SiteFooter, default } from './site-footer';
|
|
2
|
-
export type { SiteFooterProps, SiteFooterColumn, SiteFooterLink, SiteFooterSocial } from './site-footer';
|
|
1
|
+
export { SiteFooter, default } from './site-footer.js';
|
|
2
|
+
export type { SiteFooterProps, SiteFooterColumn, SiteFooterLink, SiteFooterSocial } from './site-footer.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { SiteFooter, default } from './site-footer';
|
|
1
|
+
export { SiteFooter, default } from './site-footer.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ProductMark } from '../../components/ui/product-mark';
|
|
3
|
-
import { cn } from '../../lib/utils';
|
|
2
|
+
import { ProductMark } from '../../components/ui/product-mark.js';
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
4
|
/**
|
|
5
5
|
* The footer of a product site: a brand lockup, grouped destinations, the links
|
|
6
6
|
* that leave the site, and an optional slot for the legal line.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { SiteHeader, default } from './site-header';
|
|
2
|
-
export type { SiteHeaderProps, SiteHeaderLink } from './site-header';
|
|
1
|
+
export { SiteHeader, default } from './site-header.js';
|
|
2
|
+
export type { SiteHeaderProps, SiteHeaderLink } from './site-header.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { SiteHeader, default } from './site-header';
|
|
1
|
+
export { SiteHeader, default } from './site-header.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import { type SwitcherProduct } from '../../components/ui/product-switcher';
|
|
3
|
-
import { type ProductMarkProps } from '../../components/ui/product-mark';
|
|
2
|
+
import { type SwitcherProduct } from '../../components/ui/product-switcher.js';
|
|
3
|
+
import { type ProductMarkProps } from '../../components/ui/product-mark.js';
|
|
4
4
|
/**
|
|
5
5
|
* One destination in the header's own navigation.
|
|
6
6
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ProductSwitcher, } from '../../components/ui/product-switcher';
|
|
3
|
-
import { ProductMark } from '../../components/ui/product-mark';
|
|
4
|
-
import { cn } from '../../lib/utils';
|
|
2
|
+
import { ProductSwitcher, } from '../../components/ui/product-switcher.js';
|
|
3
|
+
import { ProductMark } from '../../components/ui/product-mark.js';
|
|
4
|
+
import { cn } from '../../lib/utils.js';
|
|
5
5
|
/**
|
|
6
6
|
* The header of a product site: a brand lockup, an optional product switcher, the
|
|
7
7
|
* site's own navigation and an optional slot for application controls.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACnD,YAAY,EACV,eAAe,EACf,WAAW,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,mBAAmB,GACpB,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SiteNavbar, default } from './site-navbar.js';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ProductMarkProps } from '../../components/ui/product-mark.js';
|
|
2
|
+
/** One destination in the mobile panel, which is the site's own navigation. */
|
|
3
|
+
export type MobileNavLink = {
|
|
4
|
+
/** The text of the link. */
|
|
5
|
+
label: string;
|
|
6
|
+
/** Where the link goes. */
|
|
7
|
+
href: string;
|
|
8
|
+
/** Marks this link as the page the reader is on. */
|
|
9
|
+
current?: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** The props the mobile navigation takes. */
|
|
12
|
+
export type MobileNavProps = {
|
|
13
|
+
/** The product this navigation belongs to, drawn as the mark above the list. */
|
|
14
|
+
product: Pick<ProductMarkProps, 'id' | 'name' | 'pack'>;
|
|
15
|
+
/** Every destination, in the order a reader should meet them. */
|
|
16
|
+
links: readonly MobileNavLink[];
|
|
17
|
+
/** The accessible name of the panel, which is also the trigger's name. */
|
|
18
|
+
label: string;
|
|
19
|
+
/** The word on the trigger while the panel is closed. */
|
|
20
|
+
openLabel: string;
|
|
21
|
+
/** The word on the trigger while the panel is open. */
|
|
22
|
+
closeLabel: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The navigation for viewports below the row's own threshold.
|
|
26
|
+
*
|
|
27
|
+
* **It carries every destination, not a subset.** From the narrowest phone up to
|
|
28
|
+
* the width the horizontal row is authored for, this panel is the only way to reach
|
|
29
|
+
* a section of the site, so a link the row shows at `lg` and the panel omits at
|
|
30
|
+
* 640 is a route a reader on a small laptop cannot find at all. Both render the one
|
|
31
|
+
* array, so a destination added to one is in the other by construction rather than
|
|
32
|
+
* by remembering twice.
|
|
33
|
+
*
|
|
34
|
+
* **It is a Sheet rather than a disclosure panel of the navbar's own, and the
|
|
35
|
+
* difference is the overlay.** A panel that is a child of the bar sits over the
|
|
36
|
+
* page with the bar still visible and nothing above the rest of the document, so
|
|
37
|
+
* scrolling the page behind it moves content the reader thought was dismissed. A
|
|
38
|
+
* sheet owns a modal surface: the rest of the page is not reachable, Escape closes
|
|
39
|
+
* it, and focus is held inside it and handed back to the trigger on the way out.
|
|
40
|
+
* That is the behaviour a full-width menu over a long page needs, and it is the
|
|
41
|
+
* behaviour Prism's own navigation had to hand-write.
|
|
42
|
+
*
|
|
43
|
+
* The links are full width with a 44 pixel minimum height, because below the row's
|
|
44
|
+
* threshold this is a touch target and not a line of text, and the coarse-pointer
|
|
45
|
+
* floor in the design system asks for exactly that.
|
|
46
|
+
*/
|
|
47
|
+
export declare function MobileNav({ product, links, label, openLabel, closeLabel, }: MobileNavProps): import("react").JSX.Element;
|
|
48
|
+
//# sourceMappingURL=mobile-nav.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mobile-nav.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/mobile-nav.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAExE,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG;IAC1B,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,6CAA6C;AAC7C,MAAM,MAAM,cAAc,GAAG;IAC3B,gFAAgF;IAChF,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;IACvD,iEAAiE;IACjE,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;IAC/B,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,KAAK,EACL,KAAK,EACL,SAAS,EACT,UAAU,GACX,EAAE,cAAc,+BAsChB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Menu, X } from 'lucide-react';
|
|
5
|
+
import { Sheet, SheetContent, SheetTitle, SheetTrigger } from '../../components/ui/sheet.js';
|
|
6
|
+
import { ProductMark } from '../../components/ui/product-mark.js';
|
|
7
|
+
/**
|
|
8
|
+
* The navigation for viewports below the row's own threshold.
|
|
9
|
+
*
|
|
10
|
+
* **It carries every destination, not a subset.** From the narrowest phone up to
|
|
11
|
+
* the width the horizontal row is authored for, this panel is the only way to reach
|
|
12
|
+
* a section of the site, so a link the row shows at `lg` and the panel omits at
|
|
13
|
+
* 640 is a route a reader on a small laptop cannot find at all. Both render the one
|
|
14
|
+
* array, so a destination added to one is in the other by construction rather than
|
|
15
|
+
* by remembering twice.
|
|
16
|
+
*
|
|
17
|
+
* **It is a Sheet rather than a disclosure panel of the navbar's own, and the
|
|
18
|
+
* difference is the overlay.** A panel that is a child of the bar sits over the
|
|
19
|
+
* page with the bar still visible and nothing above the rest of the document, so
|
|
20
|
+
* scrolling the page behind it moves content the reader thought was dismissed. A
|
|
21
|
+
* sheet owns a modal surface: the rest of the page is not reachable, Escape closes
|
|
22
|
+
* it, and focus is held inside it and handed back to the trigger on the way out.
|
|
23
|
+
* That is the behaviour a full-width menu over a long page needs, and it is the
|
|
24
|
+
* behaviour Prism's own navigation had to hand-write.
|
|
25
|
+
*
|
|
26
|
+
* The links are full width with a 44 pixel minimum height, because below the row's
|
|
27
|
+
* threshold this is a touch target and not a line of text, and the coarse-pointer
|
|
28
|
+
* floor in the design system asks for exactly that.
|
|
29
|
+
*/
|
|
30
|
+
export function MobileNav({ product, links, label, openLabel, closeLabel, }) {
|
|
31
|
+
const [open, setOpen] = useState(false);
|
|
32
|
+
return (_jsxs(Sheet, { open: open, onOpenChange: setOpen, children: [_jsx(SheetTrigger, { "data-slot": "site-navbar-mobile-trigger", "aria-label": open ? closeLabel : openLabel, className: "border-border bg-card text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex size-11 shrink-0 items-center justify-center rounded-full border transition-colors focus-visible:ring-[3px] focus-visible:outline-none lg:hidden", children: open ? _jsx(X, { "aria-hidden": true, className: "size-5" }) : _jsx(Menu, { "aria-hidden": true, className: "size-5" }) }), _jsxs(SheetContent, { side: "right", className: "w-80", children: [_jsx(SheetTitle, { className: "sr-only", children: label }), _jsxs("nav", { "aria-label": label, className: "flex flex-col gap-1", children: [_jsx("div", { className: "mb-4 flex items-center", children: _jsx(ProductMark, { id: product.id, name: product.name, pack: product.pack, size: "md" }) }), links.map((link) => (_jsx("a", { href: link.href, "aria-current": link.current ? 'page' : undefined, onClick: () => setOpen(false), className: link.current
|
|
33
|
+
? 'bg-accent text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex min-h-11 items-center rounded-lg px-3 text-sm font-medium transition-colors focus-visible:ring-[3px] focus-visible:outline-none'
|
|
34
|
+
: 'text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex min-h-11 items-center rounded-lg px-3 text-sm font-medium transition-colors focus-visible:ring-[3px] focus-visible:outline-none', children: link.label }, link.href)))] })] })] }));
|
|
35
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** The props the mode toggle takes. */
|
|
2
|
+
export type ModeToggleProps = {
|
|
3
|
+
/** The accessible name of the control while the page is in light mode. */
|
|
4
|
+
lightLabel: string;
|
|
5
|
+
/** The accessible name of the control while the page is in dark mode. */
|
|
6
|
+
darkLabel: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* The light and dark control.
|
|
10
|
+
*
|
|
11
|
+
* One button rather than a menu, because the choice has two members and a menu is
|
|
12
|
+
* the shape a set of six belongs in. The icon states the mode the page is in and
|
|
13
|
+
* the name states the mode the button will move it to, which is the pairing that
|
|
14
|
+
* makes the control readable at a glance and unambiguous to a screen reader: a
|
|
15
|
+
* button labelled "dark mode" that is currently showing a sun is a control whose
|
|
16
|
+
* label and its state have to be reconciled before it can be used.
|
|
17
|
+
*
|
|
18
|
+
* **It reads the mode from the provider rather than from the document.** The class
|
|
19
|
+
* on `<html>` is the mode, so this could read `document.documentElement.classList`
|
|
20
|
+
* and would then hold a value the theme itself owns in two places. The provider is
|
|
21
|
+
* the single writer of that class, and a control that wrote it directly would be a
|
|
22
|
+
* second writer of a state every other part of the page reads.
|
|
23
|
+
*
|
|
24
|
+
* `aria-pressed` is on the control, and it is worth stating why a toggle rather than
|
|
25
|
+
* a pair of buttons: the button's accessible name changes with the mode, and a
|
|
26
|
+
* changing name on a pressed control is the combination that leaves a screen reader
|
|
27
|
+
* announcing "dark mode, pressed" for a page that is in light mode. The name
|
|
28
|
+
* describes the destination and the pressed state describes the current mode, so the
|
|
29
|
+
* two never contradict each other because neither claims to be the other.
|
|
30
|
+
*
|
|
31
|
+
* **The two labels are keyed to the mode they are shown in, not to the mode they
|
|
32
|
+
* name.** `lightLabel` is what the control is called while the page is in light
|
|
33
|
+
* mode, which is the word that sends a reader to dark mode. Reading them the other
|
|
34
|
+
* way round is the mistake this control shipped with and the test that found it:
|
|
35
|
+
* a page in light mode announced "Switch to light mode", which is a control that
|
|
36
|
+
* claims to do the thing the page is already doing.
|
|
37
|
+
*/
|
|
38
|
+
export declare function ModeToggle({ lightLabel, darkLabel }: ModeToggleProps): import("react").JSX.Element;
|
|
39
|
+
//# sourceMappingURL=mode-toggle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mode-toggle.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/mode-toggle.tsx"],"names":[],"mappings":"AAMA,uCAAuC;AACvC,MAAM,MAAM,eAAe,GAAG;IAC5B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAA;IAClB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,UAAU,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,eAAe,+BAgBpE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Moon, Sun } from 'lucide-react';
|
|
4
|
+
import { usePrismTheme } from '../../provider/provider.js';
|
|
5
|
+
/**
|
|
6
|
+
* The light and dark control.
|
|
7
|
+
*
|
|
8
|
+
* One button rather than a menu, because the choice has two members and a menu is
|
|
9
|
+
* the shape a set of six belongs in. The icon states the mode the page is in and
|
|
10
|
+
* the name states the mode the button will move it to, which is the pairing that
|
|
11
|
+
* makes the control readable at a glance and unambiguous to a screen reader: a
|
|
12
|
+
* button labelled "dark mode" that is currently showing a sun is a control whose
|
|
13
|
+
* label and its state have to be reconciled before it can be used.
|
|
14
|
+
*
|
|
15
|
+
* **It reads the mode from the provider rather than from the document.** The class
|
|
16
|
+
* on `<html>` is the mode, so this could read `document.documentElement.classList`
|
|
17
|
+
* and would then hold a value the theme itself owns in two places. The provider is
|
|
18
|
+
* the single writer of that class, and a control that wrote it directly would be a
|
|
19
|
+
* second writer of a state every other part of the page reads.
|
|
20
|
+
*
|
|
21
|
+
* `aria-pressed` is on the control, and it is worth stating why a toggle rather than
|
|
22
|
+
* a pair of buttons: the button's accessible name changes with the mode, and a
|
|
23
|
+
* changing name on a pressed control is the combination that leaves a screen reader
|
|
24
|
+
* announcing "dark mode, pressed" for a page that is in light mode. The name
|
|
25
|
+
* describes the destination and the pressed state describes the current mode, so the
|
|
26
|
+
* two never contradict each other because neither claims to be the other.
|
|
27
|
+
*
|
|
28
|
+
* **The two labels are keyed to the mode they are shown in, not to the mode they
|
|
29
|
+
* name.** `lightLabel` is what the control is called while the page is in light
|
|
30
|
+
* mode, which is the word that sends a reader to dark mode. Reading them the other
|
|
31
|
+
* way round is the mistake this control shipped with and the test that found it:
|
|
32
|
+
* a page in light mode announced "Switch to light mode", which is a control that
|
|
33
|
+
* claims to do the thing the page is already doing.
|
|
34
|
+
*/
|
|
35
|
+
export function ModeToggle({ lightLabel, darkLabel }) {
|
|
36
|
+
const { mode, toggleMode } = usePrismTheme();
|
|
37
|
+
const dark = mode === 'dark';
|
|
38
|
+
return (_jsx("button", { type: "button", "data-slot": "site-navbar-mode-toggle", onClick: toggleMode, "aria-label": dark ? darkLabel : lightLabel, "aria-pressed": dark, className: "border-border bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex size-11 shrink-0 items-center justify-center rounded-full border transition-colors focus-visible:ring-[3px] focus-visible:outline-none", children: dark ? _jsx(Sun, { "aria-hidden": true, className: "size-4" }) : _jsx(Moon, { "aria-hidden": true, className: "size-4" }) }));
|
|
39
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Mode, PackId } from '../../theming/index.js';
|
|
2
|
+
import type { SearchDialogMessages } from '../../components/ui/search-dialog.js';
|
|
3
|
+
import { type ThemePack } from './theme-menu.js';
|
|
4
|
+
import type { SwitcherProduct } from '../../components/ui/product-switcher.js';
|
|
5
|
+
import type { MobileNavLink } from './mobile-nav.js';
|
|
6
|
+
/** What the control cluster was told to render. Every field is optional. */
|
|
7
|
+
export type NavbarControlsProps = {
|
|
8
|
+
/** The product whose mark heads the mobile panel. */
|
|
9
|
+
product: {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
pack?: PackId | null;
|
|
13
|
+
};
|
|
14
|
+
/** The site's own destinations, for the panel below the row's threshold. */
|
|
15
|
+
nav: readonly MobileNavLink[];
|
|
16
|
+
/** The accessible name of the panel and of its trigger. */
|
|
17
|
+
navLabel: string;
|
|
18
|
+
/** The set of sites, or nothing for a site that is the only one. */
|
|
19
|
+
sites?: readonly SwitcherProduct[];
|
|
20
|
+
/** The `id` of the site the reader is on. */
|
|
21
|
+
currentSiteId?: string;
|
|
22
|
+
/** The accessible name of the sites menu. */
|
|
23
|
+
sitesLabel?: string;
|
|
24
|
+
/** Where the search index is served from, or nothing for no search. */
|
|
25
|
+
search?: {
|
|
26
|
+
indexUrl: string;
|
|
27
|
+
label: string;
|
|
28
|
+
hint?: string;
|
|
29
|
+
messages: SearchDialogMessages;
|
|
30
|
+
};
|
|
31
|
+
/** The packs the chooser offers, or nothing for no chooser. */
|
|
32
|
+
theme?: {
|
|
33
|
+
label: string;
|
|
34
|
+
packs?: readonly ThemePack[];
|
|
35
|
+
};
|
|
36
|
+
/** The two names of the light and dark control, or nothing for no toggle. */
|
|
37
|
+
mode?: {
|
|
38
|
+
lightLabel: string;
|
|
39
|
+
darkLabel: string;
|
|
40
|
+
};
|
|
41
|
+
/** The two names of the mobile trigger. */
|
|
42
|
+
mobileLabels: {
|
|
43
|
+
open: string;
|
|
44
|
+
close: string;
|
|
45
|
+
};
|
|
46
|
+
/** The pack a reader with no stored choice gets. */
|
|
47
|
+
defaultPack: PackId;
|
|
48
|
+
/** The mode a reader with no stored choice gets. */
|
|
49
|
+
defaultMode: Mode;
|
|
50
|
+
/** A slot for controls the consumer owns, after the ones above. */
|
|
51
|
+
actions?: React.ReactNode;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* The bar's controls, and the only client boundary in the navbar.
|
|
55
|
+
*
|
|
56
|
+
* Everything interactive in a site header is application state: what a reader has
|
|
57
|
+
* chosen, what is open, what a search found. None of it is a fact the bar can be
|
|
58
|
+
* told, so none of it can live in a server Component, and the boundary is drawn
|
|
59
|
+
* here rather than around the whole bar so that the brand lockup and the
|
|
60
|
+
* navigation stay server rendered. That is the arrangement that lets a site keep
|
|
61
|
+
* the rest of its page free of client JavaScript, which is the property three of
|
|
62
|
+
* the five NaniSoft sites are built around.
|
|
63
|
+
*
|
|
64
|
+
* **The provider is mounted here and not in the site's root layout, and that is
|
|
65
|
+
* deliberate.** A provider in the layout would wrap every page and every provider
|
|
66
|
+
* is context, so a page that never renders a control would still ship it. Mounted
|
|
67
|
+
* around five buttons, it ships with the buttons and stops there. It is also the
|
|
68
|
+
* only writer of the two attributes the boot script reads, so a choice made here
|
|
69
|
+
* is a choice the next page load resolves to the same theme.
|
|
70
|
+
*
|
|
71
|
+
* **The order is fixed and it is a reading order, not a preference.** Search first
|
|
72
|
+
* because it is the only control that answers a question the reader arrived with;
|
|
73
|
+
* then the two menus, which are choices about where to be rather than about what to
|
|
74
|
+
* do; then the mode, which is the choice that persists across every site in the
|
|
75
|
+
* family; then the mobile trigger, which is last because it is the only one that
|
|
76
|
+
* appears at the narrow end of the range and appears alone there.
|
|
77
|
+
*/
|
|
78
|
+
export declare function NavbarControls(props: NavbarControlsProps): import("react").JSX.Element | null;
|
|
79
|
+
//# sourceMappingURL=navbar-controls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navbar-controls.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/navbar-controls.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAI7E,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAIjD,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAAG;IAChC,qDAAqD;IACrD,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;IAC3D,4EAA4E;IAC5E,GAAG,EAAE,SAAS,aAAa,EAAE,CAAA;IAC7B,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,MAAM,CAAC,EAAE;QACP,QAAQ,EAAE,MAAM,CAAA;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,oBAAoB,CAAA;KAC/B,CAAA;IACD,+DAA+D;IAC/D,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;KAAE,CAAA;IACvD,6EAA6E;IAC7E,IAAI,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD,2CAA2C;IAC3C,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAA;IACnB,oDAAoD;IACpD,WAAW,EAAE,IAAI,CAAA;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,sCAsDxD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ModeToggle } from './mode-toggle.js';
|
|
4
|
+
import { SearchEntry } from './search-entry.js';
|
|
5
|
+
import { SitesMenu } from './sites-menu.js';
|
|
6
|
+
import { ThemeMenu } from './theme-menu.js';
|
|
7
|
+
import { MobileNav } from './mobile-nav.js';
|
|
8
|
+
import { PrismProvider } from '../../provider/provider.js';
|
|
9
|
+
/**
|
|
10
|
+
* The bar's controls, and the only client boundary in the navbar.
|
|
11
|
+
*
|
|
12
|
+
* Everything interactive in a site header is application state: what a reader has
|
|
13
|
+
* chosen, what is open, what a search found. None of it is a fact the bar can be
|
|
14
|
+
* told, so none of it can live in a server Component, and the boundary is drawn
|
|
15
|
+
* here rather than around the whole bar so that the brand lockup and the
|
|
16
|
+
* navigation stay server rendered. That is the arrangement that lets a site keep
|
|
17
|
+
* the rest of its page free of client JavaScript, which is the property three of
|
|
18
|
+
* the five NaniSoft sites are built around.
|
|
19
|
+
*
|
|
20
|
+
* **The provider is mounted here and not in the site's root layout, and that is
|
|
21
|
+
* deliberate.** A provider in the layout would wrap every page and every provider
|
|
22
|
+
* is context, so a page that never renders a control would still ship it. Mounted
|
|
23
|
+
* around five buttons, it ships with the buttons and stops there. It is also the
|
|
24
|
+
* only writer of the two attributes the boot script reads, so a choice made here
|
|
25
|
+
* is a choice the next page load resolves to the same theme.
|
|
26
|
+
*
|
|
27
|
+
* **The order is fixed and it is a reading order, not a preference.** Search first
|
|
28
|
+
* because it is the only control that answers a question the reader arrived with;
|
|
29
|
+
* then the two menus, which are choices about where to be rather than about what to
|
|
30
|
+
* do; then the mode, which is the choice that persists across every site in the
|
|
31
|
+
* family; then the mobile trigger, which is last because it is the only one that
|
|
32
|
+
* appears at the narrow end of the range and appears alone there.
|
|
33
|
+
*/
|
|
34
|
+
export function NavbarControls(props) {
|
|
35
|
+
const { product, nav, navLabel, sites, currentSiteId, sitesLabel, search, theme, mode, mobileLabels, defaultPack, defaultMode, actions, } = props;
|
|
36
|
+
const hasThemeControls = Boolean(theme) || Boolean(mode);
|
|
37
|
+
if (!search && !sites && !hasThemeControls && !actions && nav.length === 0)
|
|
38
|
+
return null;
|
|
39
|
+
return (_jsx(PrismProvider, { defaultPack: defaultPack, defaultMode: defaultMode, children: _jsxs("div", { className: "ms-auto flex items-center gap-2", children: [search ? (_jsx(SearchEntry, { indexUrl: search.indexUrl, label: search.label, hint: search.hint, messages: search.messages })) : null, sites && sites.length > 0 && sitesLabel ? (_jsx(SitesMenu, { sites: sites, currentId: currentSiteId, label: sitesLabel })) : null, theme ? _jsx(ThemeMenu, { label: theme.label, packs: theme.packs }) : null, mode ? _jsx(ModeToggle, { lightLabel: mode.lightLabel, darkLabel: mode.darkLabel }) : null, actions, nav.length > 0 ? (_jsx(MobileNav, { product: product, links: nav, label: navLabel, openLabel: mobileLabels.open, closeLabel: mobileLabels.close })) : null] }) }));
|
|
40
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SearchDialogProps } from '../../components/ui/search-dialog.js';
|
|
2
|
+
/** The props the search entry takes. It is the dialog's props without its close. */
|
|
3
|
+
export type SearchEntryProps = Omit<SearchDialogProps, 'onClose'>;
|
|
4
|
+
/**
|
|
5
|
+
* The search trigger, and the dialog it opens.
|
|
6
|
+
*
|
|
7
|
+
* **The dialog is loaded on the first activation, so neither the dialog nor the
|
|
8
|
+
* index is part of any page's first paint.** The index is the largest single asset
|
|
9
|
+
* on a documentation site, and a statically imported dialog is in the module graph
|
|
10
|
+
* of every page whether or not the reader ever searches. The trigger is a plain
|
|
11
|
+
* button and the cost of reaching it is one click.
|
|
12
|
+
*
|
|
13
|
+
* **The shortcut is Command-K on Apple platforms and Control-K everywhere else,
|
|
14
|
+
* and it matches rather than replaces.** The listener calls `preventDefault` so the
|
|
15
|
+
* browser's own find behaviour does not also fire, and it toggles so pressing it
|
|
16
|
+
* twice leaves the reader where they started. It is registered on the document
|
|
17
|
+
* rather than on the button, because a shortcut scoped to a control only works once
|
|
18
|
+
* that control has focus, and the point of a shortcut is to save the reader from
|
|
19
|
+
* having to find the control first.
|
|
20
|
+
*
|
|
21
|
+
* **It is icon-only at every width.** The control is not a destination, so its word
|
|
22
|
+
* is the first thing that goes when the bar runs out of room, and the row it sits in
|
|
23
|
+
* is measured rather than assumed: a labelled search control is 55 pixels wider than
|
|
24
|
+
* an icon in the same slot, and on a site whose navigation is nine Sections that is
|
|
25
|
+
* the difference between fitting at the authored breakpoint and folding the brand
|
|
26
|
+
* onto two lines. The accessible name is what replaces the word.
|
|
27
|
+
*/
|
|
28
|
+
export declare function SearchEntry(props: SearchEntryProps): import("react").JSX.Element;
|
|
29
|
+
//# sourceMappingURL=search-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-entry.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/search-entry.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AAe1E,oFAAoF;AACpF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAA;AAEjE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BAwClD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { lazy, Suspense, useEffect, useState } from 'react';
|
|
4
|
+
import { Search } from 'lucide-react';
|
|
5
|
+
/**
|
|
6
|
+
* The dialog, loaded on the first activation.
|
|
7
|
+
*
|
|
8
|
+
* Declared at module scope so the import is shared by every search entry on a page
|
|
9
|
+
* rather than re-issued per call, which is what makes a second search on the same
|
|
10
|
+
* page instant. `lazy` is React's own rather than a framework's, because this
|
|
11
|
+
* package imports no framework and has to stay installable in a bundler that is
|
|
12
|
+
* not the one its own site uses.
|
|
13
|
+
*/
|
|
14
|
+
const SearchDialog = lazy(() => import('../../components/ui/search-dialog.js').then((module) => ({ default: module.SearchDialog })));
|
|
15
|
+
/**
|
|
16
|
+
* The search trigger, and the dialog it opens.
|
|
17
|
+
*
|
|
18
|
+
* **The dialog is loaded on the first activation, so neither the dialog nor the
|
|
19
|
+
* index is part of any page's first paint.** The index is the largest single asset
|
|
20
|
+
* on a documentation site, and a statically imported dialog is in the module graph
|
|
21
|
+
* of every page whether or not the reader ever searches. The trigger is a plain
|
|
22
|
+
* button and the cost of reaching it is one click.
|
|
23
|
+
*
|
|
24
|
+
* **The shortcut is Command-K on Apple platforms and Control-K everywhere else,
|
|
25
|
+
* and it matches rather than replaces.** The listener calls `preventDefault` so the
|
|
26
|
+
* browser's own find behaviour does not also fire, and it toggles so pressing it
|
|
27
|
+
* twice leaves the reader where they started. It is registered on the document
|
|
28
|
+
* rather than on the button, because a shortcut scoped to a control only works once
|
|
29
|
+
* that control has focus, and the point of a shortcut is to save the reader from
|
|
30
|
+
* having to find the control first.
|
|
31
|
+
*
|
|
32
|
+
* **It is icon-only at every width.** The control is not a destination, so its word
|
|
33
|
+
* is the first thing that goes when the bar runs out of room, and the row it sits in
|
|
34
|
+
* is measured rather than assumed: a labelled search control is 55 pixels wider than
|
|
35
|
+
* an icon in the same slot, and on a site whose navigation is nine Sections that is
|
|
36
|
+
* the difference between fitting at the authored breakpoint and folding the brand
|
|
37
|
+
* onto two lines. The accessible name is what replaces the word.
|
|
38
|
+
*/
|
|
39
|
+
export function SearchEntry(props) {
|
|
40
|
+
const [open, setOpen] = useState(false);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const onKeyDown = (event) => {
|
|
43
|
+
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k') {
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
setOpen((value) => !value);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
document.addEventListener('keydown', onKeyDown);
|
|
49
|
+
return () => document.removeEventListener('keydown', onKeyDown);
|
|
50
|
+
}, []);
|
|
51
|
+
return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "data-slot": "site-navbar-search-trigger", onClick: () => setOpen(true), "aria-label": props.label, "aria-haspopup": "dialog", "aria-expanded": open, className: "border-border bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex size-11 shrink-0 items-center justify-center rounded-full border transition-colors focus-visible:ring-[3px] focus-visible:outline-none", children: _jsx(Search, { "aria-hidden": true, className: "size-4" }) }), open ? (_jsx(Suspense, { fallback: null, children: _jsx(SearchDialog, { ...props, onClose: () => setOpen(false) }) })) : null] }));
|
|
52
|
+
}
|