@marktiderman/genesis-ui 2.7.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/EXTENDING.md +40 -1
  2. package/SKILL.md +198 -9
  3. package/dist/{AppShell-CX0M-dfc.d.ts → AppShell-LXQykEqe.d.ts} +47 -5
  4. package/dist/{chunk-M62CHO3N.js → chunk-4C4ESW6O.js} +9 -4
  5. package/dist/chunk-4C4ESW6O.js.map +1 -0
  6. package/dist/chunk-DIV4BYXX.js +58 -0
  7. package/dist/chunk-DIV4BYXX.js.map +1 -0
  8. package/dist/chunk-FUVWKTPL.js +19 -0
  9. package/dist/chunk-FUVWKTPL.js.map +1 -0
  10. package/dist/{chunk-PLIYF6KI.js → chunk-MPI33I4K.js} +2 -2
  11. package/dist/{chunk-PLIYF6KI.js.map → chunk-MPI33I4K.js.map} +1 -1
  12. package/dist/{chunk-JA3ZKULS.js → chunk-OITWCIG2.js} +3 -3
  13. package/dist/chunk-OITWCIG2.js.map +1 -0
  14. package/dist/chunk-PKFDGGZV.js +65 -0
  15. package/dist/chunk-PKFDGGZV.js.map +1 -0
  16. package/dist/{chunk-IXGAEECT.js → chunk-RKPS7ERS.js} +9 -5
  17. package/dist/chunk-RKPS7ERS.js.map +1 -0
  18. package/dist/{chunk-TXOZMKNW.js → chunk-S7NXD37O.js} +27 -26
  19. package/dist/chunk-S7NXD37O.js.map +1 -0
  20. package/dist/{chunk-ZPPLUGLA.js → chunk-UYI3GLFJ.js} +162 -19
  21. package/dist/chunk-UYI3GLFJ.js.map +1 -0
  22. package/dist/{chunk-CDYZRZ6U.js → chunk-WGMEVX3Y.js} +2 -2
  23. package/dist/chunk-WGMEVX3Y.js.map +1 -0
  24. package/dist/chunk-ZDHWNQTR.js +552 -0
  25. package/dist/chunk-ZDHWNQTR.js.map +1 -0
  26. package/dist/components/data/index.d.ts +306 -19
  27. package/dist/components/data/index.js +1177 -284
  28. package/dist/components/data/index.js.map +1 -1
  29. package/dist/components/layout/form-page.d.ts +1 -1
  30. package/dist/components/layout/form-page.js +1 -1
  31. package/dist/components/layout/index.d.ts +2 -2
  32. package/dist/components/layout/index.js +8 -8
  33. package/dist/components/patterns/index.d.ts +1 -1
  34. package/dist/components/patterns/index.js +5 -5
  35. package/dist/components/patterns/sortable-list.js +1 -1
  36. package/dist/components/rich-text/rich-text-editor.d.ts +194 -0
  37. package/dist/components/rich-text/rich-text-editor.js +833 -0
  38. package/dist/components/rich-text/rich-text-editor.js.map +1 -0
  39. package/dist/components/rich-text/rich-text.d.ts +51 -0
  40. package/dist/components/rich-text/rich-text.js +4 -0
  41. package/dist/components/rich-text/rich-text.js.map +1 -0
  42. package/dist/components/ui/alert-dialog.d.ts +12 -1
  43. package/dist/components/ui/alert-dialog.js +1 -1
  44. package/dist/hooks/index.d.ts +4 -3
  45. package/dist/hooks/index.js +5 -4
  46. package/dist/hooks/use-data-filters.d.ts +5 -3
  47. package/dist/hooks/use-data-filters.js +2 -2
  48. package/dist/hooks/use-resource-page.d.ts +2 -1
  49. package/dist/hooks/use-resource-page.js +3 -2
  50. package/dist/hooks/use-resource-url-state.d.ts +68 -0
  51. package/dist/hooks/use-resource-url-state.js +3 -0
  52. package/dist/hooks/use-resource-url-state.js.map +1 -0
  53. package/dist/hooks/use-view-preference.d.ts +17 -2
  54. package/dist/hooks/use-view-preference.js +2 -1
  55. package/dist/index.d.ts +2 -2
  56. package/dist/index.js +32 -32
  57. package/dist/{navigation-DBwcZ6vb.d.ts → navigation-Bha0R3Fu.d.ts} +6 -3
  58. package/dist/rich-text-doc-C54fME2C.d.ts +180 -0
  59. package/dist/router/react-router.d.ts +47 -0
  60. package/dist/router/react-router.js +53 -0
  61. package/dist/router/react-router.js.map +1 -0
  62. package/dist/router/tanstack-router.d.ts +47 -0
  63. package/dist/router/tanstack-router.js +105 -0
  64. package/dist/router/tanstack-router.js.map +1 -0
  65. package/dist/{use-resource-page-Dd2VUv30.d.ts → use-resource-page-BDnnCssE.d.ts} +83 -5
  66. package/package.json +61 -14
  67. package/dist/chunk-CDYZRZ6U.js.map +0 -1
  68. package/dist/chunk-FTTNGGLA.js +0 -20
  69. package/dist/chunk-FTTNGGLA.js.map +0 -1
  70. package/dist/chunk-IXGAEECT.js.map +0 -1
  71. package/dist/chunk-JA3ZKULS.js.map +0 -1
  72. package/dist/chunk-M62CHO3N.js.map +0 -1
  73. package/dist/chunk-TXOZMKNW.js.map +0 -1
  74. package/dist/chunk-ZPPLUGLA.js.map +0 -1
@@ -41,7 +41,7 @@ interface FormPageProps extends Omit<React.FormHTMLAttributes<HTMLFormElement>,
41
41
  * ```tsx
42
42
  * <FormPage
43
43
  * title="New engagement"
44
- * description="Both the coach and the client will be notified."
44
+ * description="Both parties will be notified."
45
45
  * errors={submitFailed ? "Fix the highlighted fields." : undefined}
46
46
  * onSubmit={handleSubmit(onValid)}
47
47
  * actions={
@@ -1,4 +1,4 @@
1
- export { FormPage } from '../../chunk-PLIYF6KI.js';
1
+ export { FormPage } from '../../chunk-MPI33I4K.js';
2
2
  import '../../chunk-OZZTPE7F.js';
3
3
  import '../../chunk-NZ5WBA4R.js';
4
4
  //# sourceMappingURL=form-page.js.map
@@ -1,4 +1,5 @@
1
- export { A as AppShell, a as AppShellOptions, b as AppShellProps, N as NavItem, P as PageHeader, c as PageHeaderOptions, d as PageHeaderProps } from '../../AppShell-CX0M-dfc.js';
1
+ export { A as AppShell, a as AppShellOptions, b as AppShellProps, N as NavItem, P as PageHeader, c as PageHeaderOptions, d as PageHeaderProps, e as ParentNavigation } from '../../AppShell-LXQykEqe.js';
2
+ export { G as GenesisLinkProps, L as LinkComponent, N as NavigationNode, R as ResolvedNavigation, r as resolveNavigation } from '../../navigation-Bha0R3Fu.js';
2
3
  export { DetailPage, DetailPageProps } from './detail-page.js';
3
4
  export { FormPage, FormPageProps } from './form-page.js';
4
5
  export { D as DashboardPage, a as DashboardPageProps, G as Grid, b as GridProps, g as gridVariants } from '../../dashboard-page-C0TihRl5.js';
@@ -9,6 +10,5 @@ import 'react';
9
10
  import 'lucide-react';
10
11
  import '../../view-toggle-CahQ87PW.js';
11
12
  import '../../hooks/use-view-settings.js';
12
- import '../../navigation-DBwcZ6vb.js';
13
13
  import 'class-variance-authority/types';
14
14
  import 'class-variance-authority';
@@ -1,22 +1,22 @@
1
- export { AppShell, PageHeader } from '../../chunk-ZPPLUGLA.js';
1
+ export { AppShell, PageHeader } from '../../chunk-UYI3GLFJ.js';
2
2
  import '../../chunk-46TZGMFW.js';
3
3
  export { Container, Stack, containerVariants, stackVariants } from '../../chunk-4CQHPWJD.js';
4
- export { FormPage } from '../../chunk-PLIYF6KI.js';
5
- import '../../chunk-OZZTPE7F.js';
6
- export { Section, SettingsPage, sectionHeadingVariants } from '../../chunk-P64MFQXZ.js';
7
4
  import '../../chunk-B2GIBUQD.js';
8
5
  import '../../chunk-NPNADZHM.js';
9
6
  import '../../chunk-FK42ZGGV.js';
10
- import '../../chunk-22XB3Q6H.js';
11
7
  import '../../chunk-QJ6P2DW6.js';
12
8
  import '../../chunk-27ELYTGE.js';
13
- import '../../chunk-NWSCYLPT.js';
14
- import '../../chunk-F47U5KNW.js';
9
+ import '../../chunk-22XB3Q6H.js';
15
10
  export { DashboardPage, Grid, gridVariants } from '../../chunk-ARJI2JUV.js';
16
11
  export { DetailPage } from '../../chunk-AFZ76Q26.js';
12
+ export { FormPage } from '../../chunk-MPI33I4K.js';
13
+ import '../../chunk-OZZTPE7F.js';
14
+ export { Section, SettingsPage, sectionHeadingVariants } from '../../chunk-P64MFQXZ.js';
17
15
  export { Split, splitVariants } from '../../chunk-D2LIXA2Y.js';
18
16
  export { GAP_CLASSES, spaceScale } from '../../chunk-AVFZ4P4B.js';
17
+ import '../../chunk-NWSCYLPT.js';
18
+ import '../../chunk-F47U5KNW.js';
19
19
  import '../../chunk-NZ5WBA4R.js';
20
- import '../../chunk-CDYZRZ6U.js';
20
+ export { resolveNavigation } from '../../chunk-WGMEVX3Y.js';
21
21
  //# sourceMappingURL=index.js.map
22
22
  //# sourceMappingURL=index.js.map
@@ -2,7 +2,7 @@ export { EmptyState, EmptyStateProps, NoFeaturesFound, NoFeedbackFound, NoSearch
2
2
  export { FormDescription, FormError, FormField, FormLabel } from './form-field.js';
3
3
  export { PageLoading, PageLoadingProps, pageLoadingVariants } from './page-loading.js';
4
4
  export { SettingsRow, SettingsRowProps } from './settings-row.js';
5
- export { SortableList, SortableListItemContext, SortableListProps } from './sortable-list.js';
5
+ export { SortableList, SortableListItemContext, SortableListProps, SortableListReorder } from './sortable-list.js';
6
6
  export { StatusBadge, StatusBadgeProps, StatusBadgeStatus, statusBadgeVariants } from './status-badge.js';
7
7
  export { ToggleRow, ToggleRowProps } from './toggle-row.js';
8
8
  export { UserAvatar, UserAvatarProps, userAvatarVariants } from './user-avatar.js';
@@ -1,18 +1,18 @@
1
1
  export { ViewSettings, ViewToggle } from '../../chunk-46TZGMFW.js';
2
- export { SortableList } from '../../chunk-TXOZMKNW.js';
2
+ export { SortableList } from '../../chunk-S7NXD37O.js';
3
3
  export { StatusBadge, statusBadgeVariants } from '../../chunk-XMK3T4TA.js';
4
4
  export { ToggleRow } from '../../chunk-6M4NHHKG.js';
5
+ export { SettingsRow } from '../../chunk-A7AHVDG7.js';
5
6
  export { UserAvatar, userAvatarVariants } from '../../chunk-XBX6QMR5.js';
6
7
  import '../../chunk-LNFF2RBD.js';
7
- export { SettingsRow } from '../../chunk-A7AHVDG7.js';
8
+ export { PageLoading, pageLoadingVariants } from '../../chunk-YRYQXU3G.js';
9
+ import '../../chunk-OVU3Z2MT.js';
8
10
  import '../../chunk-FK42ZGGV.js';
9
- import '../../chunk-22XB3Q6H.js';
10
11
  import '../../chunk-QJ6P2DW6.js';
11
12
  import '../../chunk-27ELYTGE.js';
13
+ import '../../chunk-22XB3Q6H.js';
12
14
  export { EmptyState, NoFeaturesFound, NoFeedbackFound, NoSearchResults } from '../../chunk-65SPT7EA.js';
13
15
  import '../../chunk-NWSCYLPT.js';
14
- export { PageLoading, pageLoadingVariants } from '../../chunk-YRYQXU3G.js';
15
- import '../../chunk-OVU3Z2MT.js';
16
16
  export { FormDescription, FormError, FormField, FormLabel } from '../../chunk-R7QFP6EL.js';
17
17
  import '../../chunk-F47U5KNW.js';
18
18
  import '../../chunk-NZ5WBA4R.js';
@@ -1,4 +1,4 @@
1
- export { SortableList } from '../../chunk-TXOZMKNW.js';
1
+ export { SortableList } from '../../chunk-S7NXD37O.js';
2
2
  import '../../chunk-QJ6P2DW6.js';
3
3
  import '../../chunk-NZ5WBA4R.js';
4
4
  //# sourceMappingURL=sortable-list.js.map
@@ -0,0 +1,194 @@
1
+ import * as React from 'react';
2
+ import { Editor } from '@tiptap/react';
3
+ import { R as RichTextDoc, a as RichTextHeadingLevel } from '../../rich-text-doc-C54fME2C.js';
4
+ import { Node } from '@tiptap/core';
5
+
6
+ /**
7
+ * VideoEmbed — a Tiptap node for YouTube, Vimeo and Loom players.
8
+ *
9
+ * The node stores only `{ provider, id, hash?, title? }`, never a URL, and
10
+ * rebuilds the player URL from those validated parts every time it renders.
11
+ * A pasted `<iframe>` is accepted only when its `src` parses as one of the
12
+ * three hosts; any other iframe is dropped by the editor's schema.
13
+ *
14
+ * Exported for apps that assemble their own Tiptap editor and want the same
15
+ * embed node `RichTextEditor` uses.
16
+ */
17
+
18
+ declare module "@tiptap/core" {
19
+ interface Commands<ReturnType> {
20
+ videoEmbed: {
21
+ /**
22
+ * Insert a video embed from a YouTube, Vimeo or Loom URL. Fails (returns
23
+ * false, inserts nothing) for any other URL.
24
+ */
25
+ setVideoEmbed: (options: {
26
+ url: string;
27
+ title?: string;
28
+ }) => ReturnType;
29
+ };
30
+ }
31
+ }
32
+ /**
33
+ * Tiptap node for YouTube, Vimeo and Loom players, stored as
34
+ * `{ provider, id, hash?, title? }` and rebuilt from those parts on render.
35
+ * Adds the `setVideoEmbed({ url, title })` command.
36
+ *
37
+ * @stability Beta
38
+ */
39
+ declare const VideoEmbed: Node<any, any>;
40
+
41
+ /**
42
+ * RichTextEditor — a WYSIWYG editor for formatted content (headings, bold,
43
+ * italic, underline, lists, links, quotes and optional video embeds), built
44
+ * on Tiptap 3 (ProseMirror) with a Genesis `Toolbar`.
45
+ *
46
+ * Lives on its own subpath, `@marktiderman/genesis-ui/rich-text-editor`, so
47
+ * only apps that import it need the `@tiptap/*` peers. The read-only
48
+ * renderer and the server-safe helpers are on `/rich-text`.
49
+ *
50
+ * @stability Beta
51
+ */
52
+
53
+ /**
54
+ * What the editor accepts as a value: the document JSON (canonical), or an
55
+ * HTML string. HTML is parsed by the editor in the browser and reduced to
56
+ * the editor's schema, so it is a migration convenience, not a storage
57
+ * format. Output is always JSON plus derived, sanitized HTML.
58
+ */
59
+ type RichTextEditorValue = RichTextDoc | string;
60
+ /** Derived forms of the document, computed on first read. */
61
+ interface RichTextChangeDetails {
62
+ /** Sanitized HTML from `richTextToHtml`. */
63
+ readonly html: string;
64
+ /** Plain text from `richTextToPlainText`. */
65
+ readonly text: string;
66
+ /** True when there is no visible text and no embed. */
67
+ readonly isEmpty: boolean;
68
+ /** Character count of the text (what `maxLength` limits). */
69
+ readonly characters: number;
70
+ }
71
+ type RichTextToolbarItem = "heading2" | "heading3" | "heading4" | "bold" | "italic" | "underline" | "bulletList" | "orderedList" | "blockquote" | "link" | "video" | "undo" | "redo";
72
+ interface RichTextEditorLabels {
73
+ toolbar: string;
74
+ blockGroup: string;
75
+ markGroup: string;
76
+ heading2: string;
77
+ heading3: string;
78
+ heading4: string;
79
+ bold: string;
80
+ italic: string;
81
+ underline: string;
82
+ bulletList: string;
83
+ orderedList: string;
84
+ blockquote: string;
85
+ link: string;
86
+ video: string;
87
+ undo: string;
88
+ redo: string;
89
+ linkUrl: string;
90
+ linkApply: string;
91
+ linkRemove: string;
92
+ linkInvalid: string;
93
+ videoUrl: string;
94
+ videoTitle: string;
95
+ videoInsert: string;
96
+ videoInvalid: string;
97
+ cancel: string;
98
+ characterCount: (count: number, max: number | undefined) => string;
99
+ }
100
+ /** Imperative handle exposed through `ref`. */
101
+ interface RichTextEditorHandle {
102
+ /** Move focus into the editable area. */
103
+ focus: () => void;
104
+ /** Replace the content with an empty document (fires `onChange`). */
105
+ clear: () => void;
106
+ /** The current document, sanitized. */
107
+ getJSON: () => RichTextDoc;
108
+ /** The current document as sanitized HTML. */
109
+ getHTML: () => string;
110
+ /** The underlying Tiptap editor, once mounted (null during SSR/first paint). */
111
+ readonly editor: Editor | null;
112
+ }
113
+ interface RichTextEditorProps {
114
+ /**
115
+ * Controlled value. Pass back the `doc` from `onChange` synchronously; any
116
+ * other document (including an older one from a debounced or deferred
117
+ * parent) replaces the content and resets the selection.
118
+ */
119
+ value?: RichTextEditorValue;
120
+ /** Initial value for an uncontrolled editor. */
121
+ defaultValue?: RichTextEditorValue;
122
+ /**
123
+ * Called on every edit with the sanitized document. `details` derives HTML
124
+ * and text lazily, so reading only `doc` costs no serialization.
125
+ */
126
+ onChange?: (doc: RichTextDoc, details: RichTextChangeDetails) => void;
127
+ onFocus?: () => void;
128
+ onBlur?: () => void;
129
+ /**
130
+ * `id` of the editable element. A `<label htmlFor={id}>` names the editor
131
+ * (wired as `aria-labelledby`, since a contenteditable is not a labelable
132
+ * element) and clicking it focuses the editor.
133
+ */
134
+ id?: string;
135
+ /**
136
+ * Form field name. When set, a hidden input carries the document as JSON
137
+ * so a native `<form>` submission includes it.
138
+ */
139
+ name?: string;
140
+ "aria-label"?: string;
141
+ "aria-labelledby"?: string;
142
+ "aria-describedby"?: string;
143
+ /** Marks the field invalid (`aria-invalid`, destructive border). */
144
+ invalid?: boolean;
145
+ /** Placeholder shown while the document is empty. */
146
+ placeholder?: string;
147
+ /** Content is visible and selectable but not editable; the toolbar is hidden. */
148
+ readOnly?: boolean;
149
+ /** Not editable, toolbar disabled, dimmed. */
150
+ disabled?: boolean;
151
+ autoFocus?: boolean;
152
+ /** Heading levels offered in the toolbar and kept in the document. Default `[2, 3]`. Read at mount. */
153
+ headingLevels?: readonly RichTextHeadingLevel[];
154
+ /** Enable YouTube / Vimeo / Loom embeds (toolbar button and schema). Default `false`. Read at mount. */
155
+ embeds?: boolean;
156
+ /** Maximum characters. Typing and pasting stop at the limit. Read at mount. */
157
+ maxLength?: number;
158
+ /** Show the character count under the editor. On by default when `maxLength` is set. */
159
+ showCharacterCount?: boolean;
160
+ /** Toolbar items, in groups as listed. `false` hides the toolbar (shortcuts still work). */
161
+ toolbar?: false | readonly RichTextToolbarItem[];
162
+ /** Override any user-facing string (for translation). */
163
+ labels?: Partial<RichTextEditorLabels>;
164
+ /** Classes for the outer frame. */
165
+ className?: string;
166
+ /** Classes for the editable area (for example a taller `min-h-*`). */
167
+ contentClassName?: string;
168
+ /** Stable test/automation selector (emitted as `data-testid` on the frame). */
169
+ testID?: string;
170
+ }
171
+ /**
172
+ * RichTextEditor — formatted text input for lessons, notes and other
173
+ * long-form content.
174
+ *
175
+ * - **Value:** JSON is canonical (`RichTextDoc`). `onChange` hands you the
176
+ * sanitized document plus lazily derived `html`/`text`. Store the JSON;
177
+ * on the server re-run `sanitizeRichTextDoc` and derive HTML with
178
+ * `richTextToHtml` (both from `/rich-text`, no DOM needed).
179
+ * - **Security:** output goes through the same allow-list as `RichText`;
180
+ * links keep only http(s)/mailto/tel/relative URLs; embeds are rebuilt
181
+ * from a validated YouTube/Vimeo/Loom id.
182
+ * - **SSR:** the editor mounts on the client only (Tiptap
183
+ * `immediatelyRender: false`). Until then a JSON value renders read-only,
184
+ * so server HTML shows the content instead of an empty box.
185
+ * - **Keyboard:** standard shortcuts (⌘/Ctrl+B, I, U, K for link,
186
+ * ⌘/Ctrl+Alt+2/3 for headings, ⌘/Ctrl+Shift+7/8 for lists, ⌘/Ctrl+Shift+B
187
+ * for quote, ⌘/Ctrl+Z / Shift+Z), shown in each toolbar tooltip. The
188
+ * toolbar is one tab stop with arrow-key navigation (Radix Toolbar).
189
+ *
190
+ * @stability Beta
191
+ */
192
+ declare const RichTextEditor: React.ForwardRefExoticComponent<RichTextEditorProps & React.RefAttributes<RichTextEditorHandle>>;
193
+
194
+ export { type RichTextChangeDetails, RichTextDoc, RichTextEditor, type RichTextEditorHandle, type RichTextEditorLabels, type RichTextEditorProps, type RichTextEditorValue, RichTextHeadingLevel, type RichTextToolbarItem, VideoEmbed };