@lattice-php/lattice 0.18.0 → 0.20.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 (255) hide show
  1. package/README.md +1 -1
  2. package/dist/core/index.js +3 -3
  3. package/dist/core/nodes.d.ts +5 -0
  4. package/dist/core/nodes.js +8 -1
  5. package/dist/core/nodes.js.map +1 -1
  6. package/dist/core/renderer.js +1 -3
  7. package/dist/core/renderer.js.map +1 -1
  8. package/dist/core/types.d.ts +16 -4
  9. package/dist/create-app.d.ts +31 -3
  10. package/dist/create-app.js +48 -10
  11. package/dist/create-app.js.map +1 -1
  12. package/dist/effects/registry.d.ts +3 -3
  13. package/dist/effects/registry.js +4 -4
  14. package/dist/effects/registry.js.map +1 -1
  15. package/dist/events/event-names.d.ts +0 -3
  16. package/dist/events/event-names.js +0 -3
  17. package/dist/events/event-names.js.map +1 -1
  18. package/dist/form/components/base/field.d.ts +2 -2
  19. package/dist/form/components/base/field.js +2 -2
  20. package/dist/form/components/base/field.js.map +1 -1
  21. package/dist/form/components/fields/color-picker-field.d.ts +2 -0
  22. package/dist/form/components/fields/color-picker-field.js +57 -0
  23. package/dist/form/components/fields/color-picker-field.js.map +1 -0
  24. package/dist/form/components/fields/date-input.js +1 -1
  25. package/dist/form/components/fields/date-picker-field.js +1 -1
  26. package/dist/form/components/fields/date-time-input.js +1 -1
  27. package/dist/form/components/fields/file-upload.js +7 -12
  28. package/dist/form/components/fields/file-upload.js.map +1 -1
  29. package/dist/form/components/fields/number-input.js +1 -1
  30. package/dist/form/components/fields/rich-editor-field.js +36 -275
  31. package/dist/form/components/fields/rich-editor-field.js.map +1 -1
  32. package/dist/form/components/fields/row-action-menu.js +2 -2
  33. package/dist/form/components/fields/row-action-menu.js.map +1 -1
  34. package/dist/form/components/fields/row-actions.js +3 -1
  35. package/dist/form/components/fields/row-actions.js.map +1 -1
  36. package/dist/form/components/fields/row-item.js +2 -1
  37. package/dist/form/components/fields/row-item.js.map +1 -1
  38. package/dist/form/components/fields/select.js +59 -16
  39. package/dist/form/components/fields/select.js.map +1 -1
  40. package/dist/form/components/fields/table-rows.js +5 -4
  41. package/dist/form/components/fields/table-rows.js.map +1 -1
  42. package/dist/form/components/fields/text-input.js +8 -1
  43. package/dist/form/components/fields/text-input.js.map +1 -1
  44. package/dist/form/components/fields/time-input.js +1 -1
  45. package/dist/form/components/index.d.ts +1 -0
  46. package/dist/form/components/index.js +2 -1
  47. package/dist/form/embed.d.ts +1 -0
  48. package/dist/form/embed.js +2 -1
  49. package/dist/form/hooks/use-form-resolver.js.map +1 -1
  50. package/dist/form/index.js +2 -1
  51. package/dist/form/lib/conditions.d.ts +4 -10
  52. package/dist/form/lib/conditions.js.map +1 -1
  53. package/dist/form/lib/field-props.d.ts +4 -18
  54. package/dist/form/lib/field-props.js.map +1 -1
  55. package/dist/form/plugin.js +2 -0
  56. package/dist/form/plugin.js.map +1 -1
  57. package/dist/form/rich-editor/builtins.d.ts +6 -0
  58. package/dist/form/rich-editor/builtins.js +400 -0
  59. package/dist/form/rich-editor/builtins.js.map +1 -0
  60. package/dist/form/rich-editor/index.d.ts +7 -0
  61. package/dist/form/rich-editor/index.js +3 -0
  62. package/dist/form/rich-editor/registry.d.ts +67 -0
  63. package/dist/form/rich-editor/registry.js +79 -0
  64. package/dist/form/rich-editor/registry.js.map +1 -0
  65. package/dist/form/rich-editor/toolbar-button.d.ts +12 -0
  66. package/dist/form/rich-editor/toolbar-button.js +28 -0
  67. package/dist/form/rich-editor/toolbar-button.js.map +1 -0
  68. package/dist/form/types.d.ts +1 -6
  69. package/dist/format/date-time.d.ts +3 -2
  70. package/dist/format/date-time.js.map +1 -1
  71. package/dist/i18n/backend.js +1 -1
  72. package/dist/i18n/date-time.d.ts +3 -2
  73. package/dist/i18n/date-time.js.map +1 -1
  74. package/dist/i18n/index.js +3 -2
  75. package/dist/i18n/instance.js +1 -1
  76. package/dist/i18n/page-props.d.ts +3 -2
  77. package/dist/i18n/page-props.js +1 -15
  78. package/dist/i18n/page-props.js.map +1 -1
  79. package/dist/i18n/shared-props.d.ts +7 -0
  80. package/dist/i18n/shared-props.js +25 -0
  81. package/dist/i18n/shared-props.js.map +1 -0
  82. package/dist/icons/icon-renderer.js.map +1 -1
  83. package/dist/index.d.ts +5 -3
  84. package/dist/index.js +7 -6
  85. package/dist/lattice.css +119 -57
  86. package/dist/layout/components/breadcrumbs.js +3 -1
  87. package/dist/layout/components/breadcrumbs.js.map +1 -1
  88. package/dist/layout/components/callouts.js +1 -1
  89. package/dist/lib/color.d.ts +9 -0
  90. package/dist/lib/color.js +48 -0
  91. package/dist/lib/color.js.map +1 -0
  92. package/dist/notifications/api.d.ts +6 -6
  93. package/dist/notifications/api.js.map +1 -1
  94. package/dist/notifications/types.d.ts +2 -10
  95. package/dist/provider-base.js +1 -1
  96. package/dist/realtime/build-effects.js +5 -5
  97. package/dist/realtime/build-effects.js.map +1 -1
  98. package/dist/realtime/listeners.d.ts +2 -2
  99. package/dist/realtime/listeners.js.map +1 -1
  100. package/dist/realtime/subscriptions.d.ts +2 -2
  101. package/dist/realtime/subscriptions.js.map +1 -1
  102. package/dist/registry.js.map +1 -1
  103. package/dist/table/components/bulk-bar.js +5 -5
  104. package/dist/table/components/bulk-bar.js.map +1 -1
  105. package/dist/table/components/cells/badge-cell.js +4 -1
  106. package/dist/table/components/cells/badge-cell.js.map +1 -1
  107. package/dist/table/components/cells/boolean-cell.js +3 -1
  108. package/dist/table/components/cells/boolean-cell.js.map +1 -1
  109. package/dist/table/components/cells/icon-cell.js +5 -2
  110. package/dist/table/components/cells/icon-cell.js.map +1 -1
  111. package/dist/table/components/cells/image-cell.js +8 -9
  112. package/dist/table/components/cells/image-cell.js.map +1 -1
  113. package/dist/table/components/cells/money-cell.js +9 -1
  114. package/dist/table/components/cells/money-cell.js.map +1 -1
  115. package/dist/table/components/cells/number-cell.js +9 -1
  116. package/dist/table/components/cells/number-cell.js.map +1 -1
  117. package/dist/table/components/cells/text-cell.js +4 -1
  118. package/dist/table/components/cells/text-cell.js.map +1 -1
  119. package/dist/table/components/column-filter-control.js +25 -32
  120. package/dist/table/components/column-filter-control.js.map +1 -1
  121. package/dist/table/components/column-header.d.ts +3 -3
  122. package/dist/table/components/column-header.js +5 -3
  123. package/dist/table/components/column-header.js.map +1 -1
  124. package/dist/table/components/column-visibility-menu.js +6 -11
  125. package/dist/table/components/column-visibility-menu.js.map +1 -1
  126. package/dist/table/components/filter-bar.d.ts +2 -2
  127. package/dist/table/components/filter-bar.js +13 -22
  128. package/dist/table/components/filter-bar.js.map +1 -1
  129. package/dist/table/components/filter-controls.d.ts +2 -1
  130. package/dist/table/components/filter-controls.js +36 -35
  131. package/dist/table/components/filter-controls.js.map +1 -1
  132. package/dist/table/components/filter-value-input.d.ts +0 -1
  133. package/dist/table/components/filter-value-input.js +21 -20
  134. package/dist/table/components/filter-value-input.js.map +1 -1
  135. package/dist/table/components/pagination.js +16 -20
  136. package/dist/table/components/pagination.js.map +1 -1
  137. package/dist/table/components/sort-bar.d.ts +3 -3
  138. package/dist/table/components/sort-bar.js +11 -12
  139. package/dist/table/components/sort-bar.js.map +1 -1
  140. package/dist/table/components/table-search.d.ts +9 -0
  141. package/dist/table/components/table-search.js +75 -0
  142. package/dist/table/components/table-search.js.map +1 -0
  143. package/dist/table/components/table.js +72 -19
  144. package/dist/table/components/table.js.map +1 -1
  145. package/dist/table/hooks/use-expanded-rows.d.ts +8 -0
  146. package/dist/table/hooks/use-expanded-rows.js +24 -0
  147. package/dist/table/hooks/use-expanded-rows.js.map +1 -0
  148. package/dist/table/hooks/use-table.d.ts +5 -3
  149. package/dist/table/hooks/use-table.js +56 -44
  150. package/dist/table/hooks/use-table.js.map +1 -1
  151. package/dist/table/lib/payload.d.ts +3 -2
  152. package/dist/table/lib/payload.js +16 -10
  153. package/dist/table/lib/payload.js.map +1 -1
  154. package/dist/table/lib/query.d.ts +5 -5
  155. package/dist/table/lib/query.js +20 -18
  156. package/dist/table/lib/query.js.map +1 -1
  157. package/dist/table/types.d.ts +3 -26
  158. package/dist/toast/callout.js +1 -3
  159. package/dist/toast/callout.js.map +1 -1
  160. package/dist/toast/toast.d.ts +1 -5
  161. package/dist/toast/toast.js +2 -7
  162. package/dist/toast/toast.js.map +1 -1
  163. package/dist/toast/toaster.js +2 -2
  164. package/dist/toast/toaster.js.map +1 -1
  165. package/dist/types/generated.d.ts +263 -188
  166. package/dist/ui/affix-group.d.ts +2 -1
  167. package/dist/ui/affix-group.js +9 -7
  168. package/dist/ui/affix-group.js.map +1 -1
  169. package/dist/ui/avatar.d.ts +3 -0
  170. package/dist/ui/avatar.js +52 -0
  171. package/dist/ui/avatar.js.map +1 -0
  172. package/dist/ui/button.d.ts +3 -1
  173. package/dist/ui/button.js +10 -3
  174. package/dist/ui/button.js.map +1 -1
  175. package/dist/ui/chart-view.js +161 -11
  176. package/dist/ui/chart-view.js.map +1 -1
  177. package/dist/ui/click-behavior.d.ts +1 -1
  178. package/dist/ui/click-behavior.js.map +1 -1
  179. package/dist/ui/collapsible.js +1 -1
  180. package/dist/ui/color-picker.d.ts +8 -0
  181. package/dist/ui/color-picker.js +59 -0
  182. package/dist/ui/color-picker.js.map +1 -0
  183. package/dist/ui/combobox.d.ts +11 -2
  184. package/dist/ui/combobox.js +51 -8
  185. package/dist/ui/combobox.js.map +1 -1
  186. package/dist/ui/copyable-text.d.ts +7 -0
  187. package/dist/ui/copyable-text.js +21 -13
  188. package/dist/ui/copyable-text.js.map +1 -1
  189. package/dist/ui/fragment.js +1 -1
  190. package/dist/ui/fragment.js.map +1 -1
  191. package/dist/ui/heading.js +39 -21
  192. package/dist/ui/heading.js.map +1 -1
  193. package/dist/ui/icon-button.d.ts +22 -0
  194. package/dist/ui/icon-button.js +51 -0
  195. package/dist/ui/icon-button.js.map +1 -0
  196. package/dist/ui/icon.js +10 -11
  197. package/dist/ui/icon.js.map +1 -1
  198. package/dist/ui/image-preview.d.ts +12 -0
  199. package/dist/ui/image-preview.js +65 -0
  200. package/dist/ui/image-preview.js.map +1 -0
  201. package/dist/ui/image.d.ts +3 -0
  202. package/dist/ui/image.js +21 -0
  203. package/dist/ui/image.js.map +1 -0
  204. package/dist/ui/index.d.ts +2 -1
  205. package/dist/ui/index.js +4 -3
  206. package/dist/ui/info-tooltip.js +1 -1
  207. package/dist/ui/info-tooltip.js.map +1 -1
  208. package/dist/ui/input.d.ts +3 -1
  209. package/dist/ui/input.js +2 -2
  210. package/dist/ui/input.js.map +1 -1
  211. package/dist/ui/modal.js +14 -2
  212. package/dist/ui/modal.js.map +1 -1
  213. package/dist/ui/native-select.d.ts +10 -0
  214. package/dist/ui/native-select.js +23 -0
  215. package/dist/ui/native-select.js.map +1 -0
  216. package/dist/ui/plugin.js +11 -1
  217. package/dist/ui/plugin.js.map +1 -1
  218. package/dist/ui/progress.d.ts +3 -0
  219. package/dist/ui/progress.js +114 -0
  220. package/dist/ui/progress.js.map +1 -0
  221. package/dist/ui/section.js +1 -1
  222. package/dist/ui/separator.d.ts +3 -0
  223. package/dist/ui/separator.js +15 -0
  224. package/dist/ui/separator.js.map +1 -0
  225. package/dist/ui/text.js +5 -10
  226. package/dist/ui/text.js.map +1 -1
  227. package/dist/ui/tooltip.js +1 -1
  228. package/dist/ui/tree-context.d.ts +33 -0
  229. package/dist/ui/tree-context.js +137 -0
  230. package/dist/ui/tree-context.js.map +1 -0
  231. package/dist/ui/tree.d.ts +19 -0
  232. package/dist/ui/tree.js +187 -0
  233. package/dist/ui/tree.js.map +1 -0
  234. package/dist-standalone/chunks/chart-view-wJmnVu7L.js +36 -0
  235. package/dist-standalone/chunks/date-picker-field-VbH9xrQO.js +1 -0
  236. package/dist-standalone/chunks/dist-PaT1gYi_.js +2 -0
  237. package/dist-standalone/chunks/jsx-runtime-Drll_-DD.js +1 -0
  238. package/dist-standalone/chunks/locale-CXqr7LPR.js +1 -0
  239. package/dist-standalone/chunks/notifications-echo-DsfNc4Ge.js +1 -0
  240. package/dist-standalone/chunks/page-props-AIa5UR6n.js +1 -0
  241. package/dist-standalone/chunks/react-B8IZ02wI.js +1 -0
  242. package/dist-standalone/chunks/rich-editor-field-DLQTyt36.js +154 -0
  243. package/dist-standalone/chunks/subscriptions-DY2tj9Im.js +1 -0
  244. package/dist-standalone/chunks/test-id-Dh3L6Gfh.js +1 -0
  245. package/dist-standalone/chunks/use-effect-dispatcher-feEs0GCP.js +97 -0
  246. package/dist-standalone/chunks/with-selector-BwDoCrJJ.js +1 -0
  247. package/dist-standalone/lattice.css +3 -0
  248. package/dist-standalone/lattice.js +66 -0
  249. package/dist-standalone/manifest.json +20 -0
  250. package/dist-standalone/sprite.svg +1 -0
  251. package/package.json +11 -2
  252. package/resources/icons/code-xml.svg +17 -0
  253. package/resources/icons/heading.svg +17 -0
  254. package/dist/action/hooks/use-click-behavior.d.ts +0 -3
  255. package/dist/action/hooks/use-click-behavior.js +0 -3
@@ -0,0 +1,28 @@
1
+ import { IconButton } from "../../ui/icon-button.js";
2
+ import "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region resources/js/form/rich-editor/toolbar-button.tsx
5
+ /**
6
+ * The shared editor toolbar trigger: an {@link IconButton} that keeps focus in
7
+ * the editor (mousedown is prevented so clicks don't blur it, which would
8
+ * otherwise trigger a precognition request).
9
+ */
10
+ function ToolbarIconButton({ active = false, icon, label, testId, ...props }) {
11
+ return /* @__PURE__ */ jsx(IconButton, {
12
+ size: "sm",
13
+ icon,
14
+ label,
15
+ title: label,
16
+ active,
17
+ "data-test": testId,
18
+ ...props,
19
+ onMouseDown: (event) => {
20
+ event.preventDefault();
21
+ props.onMouseDown?.(event);
22
+ }
23
+ });
24
+ }
25
+ //#endregion
26
+ export { ToolbarIconButton };
27
+
28
+ //# sourceMappingURL=toolbar-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar-button.js","names":[],"sources":["../../../resources/js/form/rich-editor/toolbar-button.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\n\n/**\n * The shared editor toolbar trigger: an {@link IconButton} that keeps focus in\n * the editor (mousedown is prevented so clicks don't blur it, which would\n * otherwise trigger a precognition request).\n */\nexport function ToolbarIconButton({\n active = false,\n icon,\n label,\n testId,\n ...props\n}: React.ComponentProps<\"button\"> & {\n active?: boolean;\n icon: string;\n label: string;\n testId: string;\n}) {\n return (\n <IconButton\n size=\"sm\"\n icon={icon}\n label={label}\n title={label}\n active={active}\n data-test={testId}\n {...props}\n onMouseDown={(event) => {\n event.preventDefault();\n props.onMouseDown?.(event);\n }}\n />\n );\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,kBAAkB,EAChC,SAAS,OACT,MACA,OACA,QACA,GAAG,SAMF;CACD,OACE,oBAAC,YAAD;EACE,MAAK;EACC;EACC;EACP,OAAO;EACC;EACR,aAAW;EACX,GAAI;EACJ,cAAc,UAAU;GACtB,MAAM,eAAe;GACrB,MAAM,cAAc,KAAK;EAC3B;CACD,CAAA;AAEL"}
@@ -1,12 +1,7 @@
1
1
  import { Method } from '@inertiajs/core';
2
2
  import { NodeUnionOf } from '../core/types.js';
3
3
  import { FormFieldNodeType, FormNodeType } from '../types/generated.js';
4
- export type { Checkbox, Choice, DateInput, DateTimeInput, Form, FormNodeType, HiddenInput, NumberInput, PasswordInput, RichEditor, Select, Textarea, TextInput, TimeInput, } from '../types/generated.js';
4
+ export type { Checkbox, Choice, DateInput, DateTimeInput, Form, FormNodeType, HiddenInput, LabelAction, NumberInput, PasswordInput, RichEditor, Select, Textarea, TextInput, TimeInput, } from '../types/generated.js';
5
5
  export type FormFieldNode = NodeUnionOf<FormFieldNodeType>;
6
6
  export type FormNode = NodeUnionOf<FormNodeType>;
7
7
  export type FormMethod = Method;
8
- export type FormLabelAction = {
9
- href: string;
10
- label: string;
11
- tabIndex?: number;
12
- };
@@ -1,10 +1,11 @@
1
+ import { DateTimeStyle } from '../types/generated.js';
1
2
  export type FormatOptions = {
2
3
  locale?: string;
3
4
  timeZone?: string;
4
5
  };
5
6
  export type DateConfig = {
6
- dateStyle: string | null;
7
- timeStyle: string | null;
7
+ dateStyle: DateTimeStyle | null;
8
+ timeStyle: DateTimeStyle | null;
8
9
  month?: string | null;
9
10
  year?: string | null;
10
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"date-time.js","names":[],"sources":["../../resources/js/format/date-time.ts"],"sourcesContent":["export type FormatOptions = {\n locale?: string;\n timeZone?: string;\n};\n\nexport type DateConfig = {\n dateStyle: string | null;\n timeStyle: string | null;\n month?: string | null;\n year?: string | null;\n};\n\nexport function formatDateValue(value: unknown, date: DateConfig, options?: FormatOptions): string {\n const parsed = new Date(String(value));\n\n if (Number.isNaN(parsed.getTime())) {\n return String(value ?? \"\");\n }\n\n const intl: Intl.DateTimeFormatOptions = { timeZone: options?.timeZone };\n\n if (date.dateStyle) {\n intl.dateStyle = date.dateStyle as Intl.DateTimeFormatOptions[\"dateStyle\"];\n }\n\n if (date.timeStyle) {\n intl.timeStyle = date.timeStyle as Intl.DateTimeFormatOptions[\"timeStyle\"];\n }\n\n if (date.month) {\n intl.month = date.month as Intl.DateTimeFormatOptions[\"month\"];\n }\n\n if (date.year) {\n intl.year = date.year as Intl.DateTimeFormatOptions[\"year\"];\n }\n\n return new Intl.DateTimeFormat(options?.locale, intl).format(parsed);\n}\n\nexport function preciseDateTime(value: unknown, options?: FormatOptions): string {\n const date = new Date(String(value));\n\n if (Number.isNaN(date.getTime())) {\n return \"\";\n }\n\n const formatted = new Intl.DateTimeFormat(options?.locale, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZone: options?.timeZone,\n timeZoneName: \"short\",\n }).format(date);\n\n return options?.timeZone ? `${formatted} (${options.timeZone})` : formatted;\n}\n"],"mappings":";AAYA,SAAgB,gBAAgB,OAAgB,MAAkB,SAAiC;CACjG,MAAM,SAAS,IAAI,KAAK,OAAO,KAAK,CAAC;CAErC,IAAI,OAAO,MAAM,OAAO,QAAQ,CAAC,GAC/B,OAAO,OAAO,SAAS,EAAE;CAG3B,MAAM,OAAmC,EAAE,UAAU,SAAS,SAAS;CAEvE,IAAI,KAAK,WACP,KAAK,YAAY,KAAK;CAGxB,IAAI,KAAK,WACP,KAAK,YAAY,KAAK;CAGxB,IAAI,KAAK,OACP,KAAK,QAAQ,KAAK;CAGpB,IAAI,KAAK,MACP,KAAK,OAAO,KAAK;CAGnB,OAAO,IAAI,KAAK,eAAe,SAAS,QAAQ,IAAI,EAAE,OAAO,MAAM;AACrE;AAEA,SAAgB,gBAAgB,OAAgB,SAAiC;CAC/E,MAAM,OAAO,IAAI,KAAK,OAAO,KAAK,CAAC;CAEnC,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,GAC7B,OAAO;CAGT,MAAM,YAAY,IAAI,KAAK,eAAe,SAAS,QAAQ;EACzD,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,UAAU,SAAS;EACnB,cAAc;CAChB,CAAC,EAAE,OAAO,IAAI;CAEd,OAAO,SAAS,WAAW,GAAG,UAAU,IAAI,QAAQ,SAAS,KAAK;AACpE"}
1
+ {"version":3,"file":"date-time.js","names":[],"sources":["../../resources/js/format/date-time.ts"],"sourcesContent":["import type { DateTimeStyle } from \"@lattice-php/lattice/types/generated\";\n\nexport type FormatOptions = {\n locale?: string;\n timeZone?: string;\n};\n\nexport type DateConfig = {\n dateStyle: DateTimeStyle | null;\n timeStyle: DateTimeStyle | null;\n month?: string | null;\n year?: string | null;\n};\n\nexport function formatDateValue(value: unknown, date: DateConfig, options?: FormatOptions): string {\n const parsed = new Date(String(value));\n\n if (Number.isNaN(parsed.getTime())) {\n return String(value ?? \"\");\n }\n\n const intl: Intl.DateTimeFormatOptions = { timeZone: options?.timeZone };\n\n if (date.dateStyle) {\n intl.dateStyle = date.dateStyle;\n }\n\n if (date.timeStyle) {\n intl.timeStyle = date.timeStyle;\n }\n\n if (date.month) {\n intl.month = date.month as Intl.DateTimeFormatOptions[\"month\"];\n }\n\n if (date.year) {\n intl.year = date.year as Intl.DateTimeFormatOptions[\"year\"];\n }\n\n return new Intl.DateTimeFormat(options?.locale, intl).format(parsed);\n}\n\nexport function preciseDateTime(value: unknown, options?: FormatOptions): string {\n const date = new Date(String(value));\n\n if (Number.isNaN(date.getTime())) {\n return \"\";\n }\n\n const formatted = new Intl.DateTimeFormat(options?.locale, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZone: options?.timeZone,\n timeZoneName: \"short\",\n }).format(date);\n\n return options?.timeZone ? `${formatted} (${options.timeZone})` : formatted;\n}\n"],"mappings":";AAcA,SAAgB,gBAAgB,OAAgB,MAAkB,SAAiC;CACjG,MAAM,SAAS,IAAI,KAAK,OAAO,KAAK,CAAC;CAErC,IAAI,OAAO,MAAM,OAAO,QAAQ,CAAC,GAC/B,OAAO,OAAO,SAAS,EAAE;CAG3B,MAAM,OAAmC,EAAE,UAAU,SAAS,SAAS;CAEvE,IAAI,KAAK,WACP,KAAK,YAAY,KAAK;CAGxB,IAAI,KAAK,WACP,KAAK,YAAY,KAAK;CAGxB,IAAI,KAAK,OACP,KAAK,QAAQ,KAAK;CAGpB,IAAI,KAAK,MACP,KAAK,OAAO,KAAK;CAGnB,OAAO,IAAI,KAAK,eAAe,SAAS,QAAQ,IAAI,EAAE,OAAO,MAAM;AACrE;AAEA,SAAgB,gBAAgB,OAAgB,SAAiC;CAC/E,MAAM,OAAO,IAAI,KAAK,OAAO,KAAK,CAAC;CAEnC,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,GAC7B,OAAO;CAGT,MAAM,YAAY,IAAI,KAAK,eAAe,SAAS,QAAQ;EACzD,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,UAAU,SAAS;EACnB,cAAc;CAChB,CAAC,EAAE,OAAO,IAAI;CAEd,OAAO,SAAS,WAAW,GAAG,UAAU,IAAI,QAAQ,SAAS,KAAK;AACpE"}
@@ -1,5 +1,5 @@
1
- import { localeHeader } from "./locale.js";
2
1
  import { setConfig } from "./config.js";
2
+ import { localeHeader } from "./locale.js";
3
3
  import { ensureI18n, i18n, preloadLanguages } from "./instance.js";
4
4
  import HttpBackend from "i18next-http-backend";
5
5
  //#region resources/js/i18n/backend.ts
@@ -1,7 +1,8 @@
1
1
  import { ReactNode } from 'react';
2
+ import { DateTimeStyle } from '../types/generated.js';
2
3
  export type DateTimeProps = {
3
4
  value: unknown;
4
- dateStyle?: string | null;
5
- timeStyle?: string | null;
5
+ dateStyle?: DateTimeStyle | null;
6
+ timeStyle?: DateTimeStyle | null;
6
7
  };
7
8
  export declare function DateTime({ value, dateStyle, timeStyle, }: DateTimeProps): ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"date-time.js","names":[],"sources":["../../resources/js/i18n/date-time.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport {\n type FormatOptions,\n formatDateValue,\n preciseDateTime,\n} from \"@lattice-php/lattice/format/date-time\";\nimport { useLocale } from \"./locale\";\nimport { useTimezone } from \"./timezone\";\n\nexport type DateTimeProps = {\n value: unknown;\n dateStyle?: string | null;\n timeStyle?: string | null;\n};\n\nexport function DateTime({\n value,\n dateStyle = \"medium\",\n timeStyle = \"short\",\n}: DateTimeProps): ReactNode {\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n\n if (value === null || value === undefined || value === \"\") {\n return null;\n }\n\n const options: FormatOptions = { locale, timeZone: timezone };\n const text = formatDateValue(value, { dateStyle, timeStyle }, options);\n const iso = isoOrNull(value);\n const title = preciseDateTime(value, options);\n\n return (\n <time dateTime={iso ?? undefined} title={title || undefined}>\n {text}\n </time>\n );\n}\n\nfunction isoOrNull(value: unknown): string | null {\n const date = new Date(String(value));\n\n return Number.isNaN(date.getTime()) ? null : date.toISOString();\n}\n"],"mappings":";;;;;AAeA,SAAgB,SAAS,EACvB,OACA,YAAY,UACZ,YAAY,WACe;CAC3B,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,EAAE,aAAa,YAAY;CAEjC,IAAI,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU,IACrD,OAAO;CAGT,MAAM,UAAyB;EAAE;EAAQ,UAAU;CAAS;CAC5D,MAAM,OAAO,gBAAgB,OAAO;EAAE;EAAW;CAAU,GAAG,OAAO;CACrE,MAAM,MAAM,UAAU,KAAK;CAC3B,MAAM,QAAQ,gBAAgB,OAAO,OAAO;CAE5C,OACE,oBAAC,QAAD;EAAM,UAAU,OAAO,KAAA;EAAW,OAAO,SAAS,KAAA;YAC/C;CACG,CAAA;AAEV;AAEA,SAAS,UAAU,OAA+B;CAChD,MAAM,OAAO,IAAI,KAAK,OAAO,KAAK,CAAC;CAEnC,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,IAAI,OAAO,KAAK,YAAY;AAChE"}
1
+ {"version":3,"file":"date-time.js","names":[],"sources":["../../resources/js/i18n/date-time.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport {\n type FormatOptions,\n formatDateValue,\n preciseDateTime,\n} from \"@lattice-php/lattice/format/date-time\";\nimport type { DateTimeStyle } from \"@lattice-php/lattice/types/generated\";\nimport { useLocale } from \"./locale\";\nimport { useTimezone } from \"./timezone\";\n\nexport type DateTimeProps = {\n value: unknown;\n dateStyle?: DateTimeStyle | null;\n timeStyle?: DateTimeStyle | null;\n};\n\nexport function DateTime({\n value,\n dateStyle = \"medium\",\n timeStyle = \"short\",\n}: DateTimeProps): ReactNode {\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n\n if (value === null || value === undefined || value === \"\") {\n return null;\n }\n\n const options: FormatOptions = { locale, timeZone: timezone };\n const text = formatDateValue(value, { dateStyle, timeStyle }, options);\n const iso = isoOrNull(value);\n const title = preciseDateTime(value, options);\n\n return (\n <time dateTime={iso ?? undefined} title={title || undefined}>\n {text}\n </time>\n );\n}\n\nfunction isoOrNull(value: unknown): string | null {\n const date = new Date(String(value));\n\n return Number.isNaN(date.getTime()) ? null : date.toISOString();\n}\n"],"mappings":";;;;;AAgBA,SAAgB,SAAS,EACvB,OACA,YAAY,UACZ,YAAY,WACe;CAC3B,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,EAAE,aAAa,YAAY;CAEjC,IAAI,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU,IACrD,OAAO;CAGT,MAAM,UAAyB;EAAE;EAAQ,UAAU;CAAS;CAC5D,MAAM,OAAO,gBAAgB,OAAO;EAAE;EAAW;CAAU,GAAG,OAAO;CACrE,MAAM,MAAM,UAAU,KAAK;CAC3B,MAAM,QAAQ,gBAAgB,OAAO,OAAO;CAE5C,OACE,oBAAC,QAAD;EAAM,UAAU,OAAO,KAAA;EAAW,OAAO,SAAS,KAAA;YAC/C;CACG,CAAA;AAEV;AAEA,SAAS,UAAU,OAA+B;CAChD,MAAM,OAAO,IAAI,KAAK,OAAO,KAAK,CAAC;CAEnC,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,IAAI,OAAO,KAAK,YAAY;AAChE"}
@@ -1,9 +1,10 @@
1
1
  import { currentLocale, localeHeader, setLocale, useLocale } from "./locale.js";
2
2
  import { i18n, translate, useT } from "./instance.js";
3
3
  import { configureI18n, enableBackend } from "./backend.js";
4
- import { LocaleReload } from "./locale-reload.js";
5
4
  import { LocaleSwitcher, useLocaleOptions } from "./locale-switcher.js";
6
- import { configureI18nFromPageProps, i18nConfigFromPageProps } from "./page-props.js";
5
+ import { i18nConfigFromPageProps } from "./shared-props.js";
6
+ import { configureI18nFromPageProps } from "./page-props.js";
7
7
  import { currentTimezone, setTimezone, useTimezone } from "./timezone.js";
8
8
  import { DateTime } from "./date-time.js";
9
+ import { LocaleReload } from "./locale-reload.js";
9
10
  export { DateTime, LocaleReload, LocaleSwitcher, configureI18n, configureI18nFromPageProps, currentLocale, currentTimezone, enableBackend, i18n, i18nConfigFromPageProps, localeHeader, setLocale, setTimezone, translate, useLocale, useLocaleOptions, useT, useTimezone };
@@ -1,5 +1,5 @@
1
- import { currentLocale, subscribeLocale, useLocale } from "./locale.js";
2
1
  import { useConfig } from "./config.js";
2
+ import { currentLocale, subscribeLocale, useLocale } from "./locale.js";
3
3
  import { useCallback, useSyncExternalStore } from "react";
4
4
  import i18next from "i18next";
5
5
  //#region resources/js/i18n/instance.ts
@@ -1,3 +1,4 @@
1
- import { ConfigureI18nOptions, I18nConfig } from './backend.js';
2
- export declare function i18nConfigFromPageProps(props: unknown): I18nConfig | undefined;
1
+ import { ConfigureI18nOptions } from './backend.js';
2
+ import { i18nConfigFromPageProps } from './shared-props.js';
3
+ export { i18nConfigFromPageProps };
3
4
  export declare function configureI18nFromPageProps(props: unknown, options?: ConfigureI18nOptions): Promise<void>;
@@ -1,20 +1,6 @@
1
1
  import { configureI18n } from "./backend.js";
2
+ import { i18nConfigFromPageProps } from "./shared-props.js";
2
3
  //#region resources/js/i18n/page-props.ts
3
- function isRecord(value) {
4
- return typeof value === "object" && value !== null;
5
- }
6
- function isStringArray(value) {
7
- return Array.isArray(value) && value.every((item) => typeof item === "string");
8
- }
9
- function isI18nConfig(value) {
10
- return isRecord(value) && typeof value.enabled === "boolean" && typeof value.saveMissing === "boolean" && isStringArray(value.locales) && isStringArray(value.preloadLocales) && (value.timezone === void 0 || value.timezone === null || typeof value.timezone === "string");
11
- }
12
- function i18nConfigFromPageProps(props) {
13
- if (!isRecord(props)) return;
14
- const shared = props.lattice;
15
- const config = isRecord(shared) ? shared.i18n : void 0;
16
- return isI18nConfig(config) ? config : void 0;
17
- }
18
4
  function configureI18nFromPageProps(props, options = {}) {
19
5
  return configureI18n(i18nConfigFromPageProps(props), options);
20
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"page-props.js","names":[],"sources":["../../resources/js/i18n/page-props.ts"],"sourcesContent":["import { configureI18n, type ConfigureI18nOptions, type I18nConfig } from \"./backend\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isI18nConfig(value: unknown): value is I18nConfig {\n return (\n isRecord(value) &&\n typeof value.enabled === \"boolean\" &&\n typeof value.saveMissing === \"boolean\" &&\n isStringArray(value.locales) &&\n isStringArray(value.preloadLocales) &&\n (value.timezone === undefined || value.timezone === null || typeof value.timezone === \"string\")\n );\n}\n\nexport function i18nConfigFromPageProps(props: unknown): I18nConfig | undefined {\n if (!isRecord(props)) {\n return undefined;\n }\n\n const shared = props.lattice;\n const config = isRecord(shared) ? shared.i18n : undefined;\n\n return isI18nConfig(config) ? config : undefined;\n}\n\nexport function configureI18nFromPageProps(\n props: unknown,\n options: ConfigureI18nOptions = {},\n): Promise<void> {\n return configureI18n(i18nConfigFromPageProps(props), options);\n}\n"],"mappings":";;AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,cAAc,OAAmC;CACxD,OAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAO,SAAS,OAAO,SAAS,QAAQ;AAC/E;AAEA,SAAS,aAAa,OAAqC;CACzD,OACE,SAAS,KAAK,KACd,OAAO,MAAM,YAAY,aACzB,OAAO,MAAM,gBAAgB,aAC7B,cAAc,MAAM,OAAO,KAC3B,cAAc,MAAM,cAAc,MACjC,MAAM,aAAa,KAAA,KAAa,MAAM,aAAa,QAAQ,OAAO,MAAM,aAAa;AAE1F;AAEA,SAAgB,wBAAwB,OAAwC;CAC9E,IAAI,CAAC,SAAS,KAAK,GACjB;CAGF,MAAM,SAAS,MAAM;CACrB,MAAM,SAAS,SAAS,MAAM,IAAI,OAAO,OAAO,KAAA;CAEhD,OAAO,aAAa,MAAM,IAAI,SAAS,KAAA;AACzC;AAEA,SAAgB,2BACd,OACA,UAAgC,CAAC,GAClB;CACf,OAAO,cAAc,wBAAwB,KAAK,GAAG,OAAO;AAC9D"}
1
+ {"version":3,"file":"page-props.js","names":[],"sources":["../../resources/js/i18n/page-props.ts"],"sourcesContent":["import { configureI18n, type ConfigureI18nOptions } from \"./backend\";\nimport { i18nConfigFromPageProps } from \"./shared-props\";\n\nexport { i18nConfigFromPageProps };\n\nexport function configureI18nFromPageProps(\n props: unknown,\n options: ConfigureI18nOptions = {},\n): Promise<void> {\n return configureI18n(i18nConfigFromPageProps(props), options);\n}\n"],"mappings":";;;AAKA,SAAgB,2BACd,OACA,UAAgC,CAAC,GAClB;CACf,OAAO,cAAc,wBAAwB,KAAK,GAAG,OAAO;AAC9D"}
@@ -0,0 +1,7 @@
1
+ import { I18nConfig } from '../types/generated.js';
2
+ /**
3
+ * Parse the backend-shared `lattice.i18n` Inertia prop. Lives apart from the
4
+ * configure entrypoint so callers can inspect the prop without pulling the
5
+ * i18next backend into their bundle.
6
+ */
7
+ export declare function i18nConfigFromPageProps(props: unknown): I18nConfig | undefined;
@@ -0,0 +1,25 @@
1
+ //#region resources/js/i18n/shared-props.ts
2
+ function isRecord(value) {
3
+ return typeof value === "object" && value !== null;
4
+ }
5
+ function isStringArray(value) {
6
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
7
+ }
8
+ function isI18nConfig(value) {
9
+ return isRecord(value) && typeof value.enabled === "boolean" && typeof value.saveMissing === "boolean" && isStringArray(value.locales) && isStringArray(value.preloadLocales) && (value.timezone === void 0 || value.timezone === null || typeof value.timezone === "string");
10
+ }
11
+ /**
12
+ * Parse the backend-shared `lattice.i18n` Inertia prop. Lives apart from the
13
+ * configure entrypoint so callers can inspect the prop without pulling the
14
+ * i18next backend into their bundle.
15
+ */
16
+ function i18nConfigFromPageProps(props) {
17
+ if (!isRecord(props)) return;
18
+ const shared = props.lattice;
19
+ const config = isRecord(shared) ? shared.i18n : void 0;
20
+ return isI18nConfig(config) ? config : void 0;
21
+ }
22
+ //#endregion
23
+ export { i18nConfigFromPageProps };
24
+
25
+ //# sourceMappingURL=shared-props.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-props.js","names":[],"sources":["../../resources/js/i18n/shared-props.ts"],"sourcesContent":["import type { I18nConfig } from \"@lattice-php/lattice/types/generated\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isI18nConfig(value: unknown): value is I18nConfig {\n return (\n isRecord(value) &&\n typeof value.enabled === \"boolean\" &&\n typeof value.saveMissing === \"boolean\" &&\n isStringArray(value.locales) &&\n isStringArray(value.preloadLocales) &&\n (value.timezone === undefined || value.timezone === null || typeof value.timezone === \"string\")\n );\n}\n\n/**\n * Parse the backend-shared `lattice.i18n` Inertia prop. Lives apart from the\n * configure entrypoint so callers can inspect the prop without pulling the\n * i18next backend into their bundle.\n */\nexport function i18nConfigFromPageProps(props: unknown): I18nConfig | undefined {\n if (!isRecord(props)) {\n return undefined;\n }\n\n const shared = props.lattice;\n const config = isRecord(shared) ? shared.i18n : undefined;\n\n return isI18nConfig(config) ? config : undefined;\n}\n"],"mappings":";AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,cAAc,OAAmC;CACxD,OAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAO,SAAS,OAAO,SAAS,QAAQ;AAC/E;AAEA,SAAS,aAAa,OAAqC;CACzD,OACE,SAAS,KAAK,KACd,OAAO,MAAM,YAAY,aACzB,OAAO,MAAM,gBAAgB,aAC7B,cAAc,MAAM,OAAO,KAC3B,cAAc,MAAM,cAAc,MACjC,MAAM,aAAa,KAAA,KAAa,MAAM,aAAa,QAAQ,OAAO,MAAM,aAAa;AAE1F;;;;;;AAOA,SAAgB,wBAAwB,OAAwC;CAC9E,IAAI,CAAC,SAAS,KAAK,GACjB;CAGF,MAAM,SAAS,MAAM;CACrB,MAAM,SAAS,SAAS,MAAM,IAAI,OAAO,OAAO,KAAA;CAEhD,OAAO,aAAa,MAAM,IAAI,SAAS,KAAA;AACzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"icon-renderer.js","names":[],"sources":["../../resources/js/icons/icon-renderer.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Icon, useSprite } from \"./sprite\";\n\nexport type IconRendererProps = {\n className?: string;\n icon: string;\n};\n\nexport type IconRendererFunction = (props: IconRendererProps) => ReactNode;\n\ntype IconRendererProviderProps = {\n children: ReactNode;\n mode?: \"replace\" | \"stack\";\n renderer: IconRendererFunction;\n};\n\nconst IconRenderersContext = createContext<IconRendererFunction[]>([]);\nconst loggedMissingIcons = new Set<string>();\n\nexport function IconRendererProvider({\n children,\n mode = \"stack\",\n renderer,\n}: IconRendererProviderProps) {\n const parentRenderers = useContext(IconRenderersContext);\n const renderers = useMemo(\n () => (mode === \"replace\" ? [renderer] : [renderer, ...parentRenderers]),\n [mode, parentRenderers, renderer],\n );\n\n return (\n <IconRenderersContext.Provider value={renderers}>{children}</IconRenderersContext.Provider>\n );\n}\n\nexport function IconRenderer({ className, icon }: IconRendererProps) {\n const renderers = useContext(IconRenderersContext);\n const { ids } = useSprite();\n\n // Custom renderers (the override stack) take precedence over the sprite.\n for (const renderer of renderers) {\n const rendered = renderer({ className, icon });\n\n if (rendered !== null && rendered !== undefined && rendered !== false) {\n return rendered;\n }\n }\n\n // When the sprite is wired and the icon is genuinely absent, show a visible\n // marker. When `ids` is unknown (not yet wired), optimistically emit the\n // sprite reference rather than crying wolf.\n if (ids && !ids.includes(icon)) {\n logMissingIcon(icon);\n return <MissingIcon className={className} />;\n }\n\n return <Icon className={className} name={icon} />;\n}\n\nfunction MissingIcon({ className }: { className?: string }) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn(\"size-lt-icon-md text-lt-muted-fg\", className)}\n data-lattice-missing-icon=\"\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\nfunction logMissingIcon(icon: string): void {\n if (!import.meta.env.DEV || loggedMissingIcons.has(icon)) {\n return;\n }\n\n loggedMissingIcons.add(icon);\n console.log(`[Lattice] Missing icon renderer for \"${icon}\".`);\n}\n"],"mappings":";;;;;AAkBA,IAAM,uBAAuB,cAAsC,CAAC,CAAC;AAGrE,SAAgB,qBAAqB,EACnC,UACA,OAAO,SACP,YAC4B;CAC5B,MAAM,kBAAkB,WAAW,oBAAoB;CACvD,MAAM,YAAY,cACT,SAAS,YAAY,CAAC,QAAQ,IAAI,CAAC,UAAU,GAAG,eAAe,GACtE;EAAC;EAAM;EAAiB;CAAQ,CAClC;CAEA,OACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAY;CAAwC,CAAA;AAE9F;AAEA,SAAgB,aAAa,EAAE,WAAW,QAA2B;CACnE,MAAM,YAAY,WAAW,oBAAoB;CACjD,MAAM,EAAE,QAAQ,UAAU;CAG1B,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,WAAW,SAAS;GAAE;GAAW;EAAK,CAAC;EAE7C,IAAI,aAAa,QAAQ,aAAa,KAAA,KAAa,aAAa,OAC9D,OAAO;CAEX;CAKA,IAAI,OAAO,CAAC,IAAI,SAAS,IAAI,GAE3B,OAAO,oBAAC,aAAD,EAAwB,UAAY,CAAA;CAG7C,OAAO,oBAAC,MAAD;EAAiB;EAAW,MAAM;CAAO,CAAA;AAClD;AAEA,SAAS,YAAY,EAAE,aAAqC;CAC1D,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,WAAW,GAAG,oCAAoC,SAAS;EAC3D,6BAA0B;EAC1B,MAAK;EACL,QAAO;EACP,eAAc;EACd,gBAAe;EACf,aAAY;EACZ,SAAQ;YATV;GAWE,oBAAC,UAAD;IAAQ,IAAG;IAAK,IAAG;IAAK,GAAE;GAAM,CAAA;GAChC,oBAAC,QAAD,EAAM,GAAE,uCAAwC,CAAA;GAChD,oBAAC,QAAD,EAAM,GAAE,aAAc,CAAA;EACnB;;AAET"}
1
+ {"version":3,"file":"icon-renderer.js","names":[],"sources":["../../resources/js/icons/icon-renderer.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Icon, useSprite } from \"./sprite\";\n\nexport type IconRendererProps = {\n className?: string;\n icon: string;\n};\n\nexport type IconRendererFunction = (props: IconRendererProps) => ReactNode;\n\ntype IconRendererProviderProps = {\n children: ReactNode;\n mode?: \"replace\" | \"stack\";\n renderer: IconRendererFunction;\n};\n\nconst IconRenderersContext = createContext<IconRendererFunction[]>([]);\nconst loggedMissingIcons = new Set<string>();\n\nexport function IconRendererProvider({\n children,\n mode = \"stack\",\n renderer,\n}: IconRendererProviderProps) {\n const parentRenderers = useContext(IconRenderersContext);\n const renderers = useMemo(\n () => (mode === \"replace\" ? [renderer] : [renderer, ...parentRenderers]),\n [mode, parentRenderers, renderer],\n );\n\n return (\n <IconRenderersContext.Provider value={renderers}>{children}</IconRenderersContext.Provider>\n );\n}\n\nexport function IconRenderer({ className, icon }: IconRendererProps) {\n const renderers = useContext(IconRenderersContext);\n const { ids } = useSprite();\n\n for (const renderer of renderers) {\n const rendered = renderer({ className, icon });\n\n if (rendered !== null && rendered !== undefined && rendered !== false) {\n return rendered;\n }\n }\n\n // When the sprite is wired and the icon is genuinely absent, show a visible\n // marker. When `ids` is unknown (not yet wired), optimistically emit the\n // sprite reference rather than crying wolf.\n if (ids && !ids.includes(icon)) {\n logMissingIcon(icon);\n return <MissingIcon className={className} />;\n }\n\n return <Icon className={className} name={icon} />;\n}\n\nfunction MissingIcon({ className }: { className?: string }) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn(\"size-lt-icon-md text-lt-muted-fg\", className)}\n data-lattice-missing-icon=\"\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\nfunction logMissingIcon(icon: string): void {\n if (!import.meta.env.DEV || loggedMissingIcons.has(icon)) {\n return;\n }\n\n loggedMissingIcons.add(icon);\n console.log(`[Lattice] Missing icon renderer for \"${icon}\".`);\n}\n"],"mappings":";;;;;AAkBA,IAAM,uBAAuB,cAAsC,CAAC,CAAC;AAGrE,SAAgB,qBAAqB,EACnC,UACA,OAAO,SACP,YAC4B;CAC5B,MAAM,kBAAkB,WAAW,oBAAoB;CACvD,MAAM,YAAY,cACT,SAAS,YAAY,CAAC,QAAQ,IAAI,CAAC,UAAU,GAAG,eAAe,GACtE;EAAC;EAAM;EAAiB;CAAQ,CAClC;CAEA,OACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAY;CAAwC,CAAA;AAE9F;AAEA,SAAgB,aAAa,EAAE,WAAW,QAA2B;CACnE,MAAM,YAAY,WAAW,oBAAoB;CACjD,MAAM,EAAE,QAAQ,UAAU;CAE1B,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,WAAW,SAAS;GAAE;GAAW;EAAK,CAAC;EAE7C,IAAI,aAAa,QAAQ,aAAa,KAAA,KAAa,aAAa,OAC9D,OAAO;CAEX;CAKA,IAAI,OAAO,CAAC,IAAI,SAAS,IAAI,GAE3B,OAAO,oBAAC,aAAD,EAAwB,UAAY,CAAA;CAG7C,OAAO,oBAAC,MAAD;EAAiB;EAAW,MAAM;CAAO,CAAA;AAClD;AAEA,SAAS,YAAY,EAAE,aAAqC;CAC1D,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,WAAW,GAAG,oCAAoC,SAAS;EAC3D,6BAA0B;EAC1B,MAAK;EACL,QAAO;EACP,eAAc;EACd,gBAAe;EACf,aAAY;EACZ,SAAQ;YATV;GAWE,oBAAC,UAAD;IAAQ,IAAG;IAAK,IAAG;IAAK,GAAE;GAAM,CAAA;GAChC,oBAAC,QAAD,EAAM,GAAE,uCAAwC,CAAA;GAChD,oBAAC,QAAD,EAAM,GAAE,aAAc,CAAA;EACnB;;AAET"}
package/dist/index.d.ts CHANGED
@@ -4,9 +4,10 @@ export { chatComponents } from './chat/plugin.js';
4
4
  export { getActionEffects, isActionEffect, dispatchEffects, dispatchActionError, } from './effects/dispatch.js';
5
5
  export { useEffectDispatcher } from './effects/use-effect-dispatcher.js';
6
6
  export { builtinEffectHandlers, effectHandler, mergeEffectHandlers } from './effects/registry.js';
7
+ export { registerRichEditorExtension } from './form/rich-editor/registry.js';
7
8
  export { initializeTheme, updateAppearance, useAppearance } from './appearance/index.js';
8
9
  export { copyToClipboard, useClipboard } from './clipboard/index.js';
9
- export { createLatticeApp, type CreateLatticeAppOptions } from './create-app.js';
10
+ export { createLatticeApp, type CreateLatticeAppI18nOptions, type CreateLatticeAppOptions, } from './create-app.js';
10
11
  export { EventBridge } from './event-bridge.js';
11
12
  export { Icon, IconRenderer, IconRendererProvider, SpriteProvider } from './icons/index.js';
12
13
  export { createLayoutResolver, createPageResolver, pageComponentName, withVisitHeaders, } from './inertia.js';
@@ -25,13 +26,14 @@ export type { ButtonVariant } from './ui/button.js';
25
26
  export type { ReloadComponentEvent } from './events/event-names.js';
26
27
  export type { ComponentProps, KnownPageContainer, LayoutPayload, Node, NodeOfType, NodeProps, NodeType, PageContainer, PageBreadcrumb, PagePayload, PropsOf, RendererComponent, RendererComponentModule, RendererComponentProps, Schema, UnknownComponent, WireNode, } from './core/types.js';
27
28
  export { RealtimeListeners } from './realtime/listeners.js';
28
- export type { ChannelVisibility, DateFormat, ListenerPayload, NumberFormat, } from './types/generated.js';
29
+ export type { ChannelVisibility, DateFormat, Listen, NumberFormat } from './types/generated.js';
29
30
  export { columnCell } from './table/registry.js';
30
31
  export type { ColumnCellArgs, ColumnCellComponent, ColumnRegistry } from './table/registry.js';
31
32
  export type { ColumnProps, ColumnPropsOf } from './table/types.js';
32
33
  export type { Method } from '@inertiajs/core';
33
34
  export type { ActionEffect, ActionResponse } from './effects/dispatch.js';
34
- export type { EffectHandler, EffectHandlerRegistry, EffectOf, EffectProps, } from './effects/registry.js';
35
+ export type { EffectHandler, EffectHandlerRegistry, EffectOf, EffectProps, EffectPropsOf, } from './effects/registry.js';
36
+ export type { EditorExtensionPayloadOf, EditorExtensionProps, RichEditorExtensionDefinition, ToolbarButton, ToolbarControl, ToolbarItem, } from './form/rich-editor/registry.js';
35
37
  export type { Appearance, ResolvedAppearance, UseAppearanceReturn } from './appearance/index.js';
36
38
  export type { CopiedValue, CopyFn, UseClipboardReturn } from './clipboard/index.js';
37
39
  export type { Callout, ToastMessage, Variant } from './toast/index.js';
package/dist/index.js CHANGED
@@ -2,16 +2,16 @@ import { initializeTheme, updateAppearance, useAppearance } from "./appearance/i
2
2
  import { createPlugin, createRegistry, eagerComponent, extendRegistry, lazyComponent } from "./core/registry.js";
3
3
  import { useColumnRegistry, useComponentRegistry } from "./core/registry-context.js";
4
4
  import { LATTICE_EVENT } from "./events/event-names.js";
5
- import { LATTICE_REF_HEADER, withRefHeader } from "./core/component-ref.js";
6
- import { withHeaders } from "./core/headers.js";
5
+ import { onToast, showToast } from "./toast/toast.js";
6
+ import { onCallout } from "./toast/callout.js";
7
7
  import { Icon, SpriteProvider } from "./icons/sprite.js";
8
8
  import { IconRenderer, IconRendererProvider } from "./icons/icon-renderer.js";
9
9
  import { CollapsedContext, useCollapsed } from "./core/collapsed-context.js";
10
10
  import { Renderer } from "./core/renderer.js";
11
- import { onToast, showToast } from "./toast/toast.js";
12
- import { onCallout } from "./toast/callout.js";
13
- import { EventBridge } from "./event-bridge.js";
14
11
  import { Toaster } from "./toast/toaster.js";
12
+ import { EventBridge } from "./event-bridge.js";
13
+ import { LATTICE_REF_HEADER, withRefHeader } from "./core/component-ref.js";
14
+ import { withHeaders } from "./core/headers.js";
15
15
  import Callouts from "./layout/components/callouts.js";
16
16
  import { builtinEffectHandlers, effectHandler, mergeEffectHandlers } from "./effects/registry.js";
17
17
  import { dispatchActionError, dispatchEffects, getActionEffects, isActionEffect } from "./effects/dispatch.js";
@@ -27,6 +27,7 @@ import { copyToClipboard } from "./ui/copyable-text.js";
27
27
  import { columnCell } from "./table/registry.js";
28
28
  import { registry } from "./registry.js";
29
29
  import { createLatticeApp } from "./create-app.js";
30
+ import { registerRichEditorExtension } from "./form/rich-editor/registry.js";
30
31
  import { useClipboard } from "./clipboard/index.js";
31
32
  import { Provider } from "./provider.js";
32
- export { Callouts, EventBridge, Icon, IconRenderer, IconRendererProvider, LATTICE_EVENT, LATTICE_REF_HEADER, OutletContext, Provider, RealtimeListeners, Renderer, SchemaLayout, CollapsedContext as SidebarCollapsedContext, SpriteProvider, Toaster, builtinEffectHandlers, chatComponents, columnCell, copyToClipboard, createLatticeApp, createLayoutResolver, createPageResolver, createPlugin, createRegistry, dispatchActionError, dispatchEffects, eagerComponent, effectHandler, extendRegistry, getActionEffects, initializeTheme, isActionEffect, layoutComponents, lazyComponent, mergeEffectHandlers, onCallout, onToast, pageComponentName, registry, showToast, updateAppearance, useAppearance, useChat, useClipboard, useColumnRegistry, useComponentRegistry, useEffectDispatcher, useCollapsed as useSidebarCollapsed, withHeaders, withRefHeader, withVisitHeaders };
33
+ export { Callouts, EventBridge, Icon, IconRenderer, IconRendererProvider, LATTICE_EVENT, LATTICE_REF_HEADER, OutletContext, Provider, RealtimeListeners, Renderer, SchemaLayout, CollapsedContext as SidebarCollapsedContext, SpriteProvider, Toaster, builtinEffectHandlers, chatComponents, columnCell, copyToClipboard, createLatticeApp, createLayoutResolver, createPageResolver, createPlugin, createRegistry, dispatchActionError, dispatchEffects, eagerComponent, effectHandler, extendRegistry, getActionEffects, initializeTheme, isActionEffect, layoutComponents, lazyComponent, mergeEffectHandlers, onCallout, onToast, pageComponentName, registerRichEditorExtension, registry, showToast, updateAppearance, useAppearance, useChat, useClipboard, useColumnRegistry, useComponentRegistry, useEffectDispatcher, useCollapsed as useSidebarCollapsed, withHeaders, withRefHeader, withVisitHeaders };
package/dist/lattice.css CHANGED
@@ -27,7 +27,6 @@
27
27
  --lt-success-fg: var(--success-foreground, oklch(0.985 0 0));
28
28
  --lt-info: var(--info, oklch(0.62 0.14 240));
29
29
  --lt-info-fg: var(--info-foreground, oklch(0.985 0 0));
30
- /* Interaction states (hover / active / disabled) */
31
30
  --lt-primary-hover: var(--primary-hover, oklch(0.43 0.092 182));
32
31
  --lt-primary-active: var(--primary-active, oklch(0.39 0.092 182));
33
32
  --lt-danger-hover: var(--destructive-hover, oklch(0.53 0.21 27.3));
@@ -62,15 +61,14 @@
62
61
  --lt-control-h-lg: 2.5rem;
63
62
 
64
63
  /* Table cell padding — table density lever */
65
- --lt-table-cell-x: calc(var(--spacing) * 4); /* 1rem */
66
- --lt-table-cell-y: calc(var(--spacing) * 4); /* 1rem */
64
+ --lt-table-cell-x: calc(var(--spacing) * 4);
65
+ --lt-table-cell-y: calc(var(--spacing) * 4);
67
66
 
68
67
  --lt-font-weight-normal: 400;
69
68
  --lt-font-weight-medium: 500;
70
69
  --lt-font-weight-semibold: 600;
71
70
  --lt-font-weight-bold: 700;
72
71
 
73
- /* Elevation */
74
72
  --lt-shadow-xs: 0 1px 1px 0 oklch(0 0 0 / 0.04);
75
73
  --lt-shadow-sm: 0 1px 2px 0 oklch(0 0 0 / 0.05);
76
74
  --lt-shadow-md:
@@ -78,7 +76,6 @@
78
76
  --lt-shadow-lg:
79
77
  0 8px 16px -4px oklch(0 0 0 / 0.12), 0 2px 4px -2px oklch(0 0 0 / 0.08);
80
78
 
81
- /* Z-index scale */
82
79
  --lt-z-dropdown: 1000;
83
80
  --lt-z-sticky: 1100;
84
81
  --lt-z-overlay: 1200;
@@ -86,17 +83,15 @@
86
83
  --lt-z-popover: 1400;
87
84
  --lt-z-toast: 1500;
88
85
 
89
- /* Motion */
90
86
  --lt-duration-fast: 120ms;
91
87
  --lt-duration-base: 160ms;
92
88
 
93
- /* Layout dimensions */
94
89
  --lt-sidebar-w: 16rem;
95
90
  --lt-sidebar-w-collapsed: 4rem;
96
91
  --lt-container-max: 80rem;
97
92
 
98
93
  /* Card / section content inset — the gutter apps can break out of */
99
- --lt-gutter: calc(var(--spacing) * 6); /* 1.5rem */
94
+ --lt-gutter: calc(var(--spacing) * 6);
100
95
 
101
96
  color-scheme: light;
102
97
  }
@@ -129,7 +124,6 @@
129
124
  --lt-info: var(--info, oklch(0.7 0.14 240));
130
125
  --lt-info-fg: var(--info-foreground, oklch(0.205 0 0));
131
126
 
132
- /* Interaction states (dark) */
133
127
  --lt-primary-hover: var(--primary-hover, oklch(0.79 0.105 182));
134
128
  --lt-primary-active: var(--primary-active, oklch(0.84 0.105 182));
135
129
  --lt-danger-hover: var(--destructive-hover, oklch(0.47 0.13 26));
@@ -219,7 +213,6 @@
219
213
  "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
220
214
  "Segoe UI Symbol", "Noto Color Emoji";
221
215
 
222
- /* Base spacing unit */
223
216
  --spacing: 0.25rem;
224
217
 
225
218
  --text-xs: 0.625rem;
@@ -293,12 +286,41 @@
293
286
  }
294
287
 
295
288
  /*
296
- * Status colours for Badge and Icon table cells. Each tone sets a soft
297
- * background and a readable foreground in oklch; the `.dark` block swaps them.
298
- * Defined here (not as utility strings in the renderer) so the palette lives
299
- * with the theme and can be overridden, and so the cells can pick a tone by
300
- * name without Tailwind needing to see every class. Gray follows the muted token.
289
+ * Named colours. Semantic names alias the theme tokens; hue names carry their
290
+ * own oklch values with `.dark` overrides. Renderers resolve a named colour to
291
+ * `var(--lt-color-<name>)` for paint, or to an `.lt-tone-<name>` class for the
292
+ * soft-background/strong-foreground pair used by badge and icon cells. Defined
293
+ * here (not as utility strings in the renderers) so the palette lives with the
294
+ * theme and can be overridden, and so a colour can be picked by name at
295
+ * runtime without Tailwind needing to see every class.
301
296
  */
297
+ :root {
298
+ --lt-color-default: var(--lt-fg);
299
+ --lt-color-muted: var(--lt-muted-fg);
300
+ --lt-color-primary: var(--lt-primary);
301
+ --lt-color-success: var(--lt-success);
302
+ --lt-color-info: var(--lt-info);
303
+ --lt-color-warning: var(--lt-warning);
304
+ --lt-color-danger: var(--lt-danger);
305
+ --lt-color-gray: var(--lt-muted-fg);
306
+ --lt-color-red: oklch(0.51 0.19 27);
307
+ --lt-color-orange: oklch(0.55 0.14 55);
308
+ --lt-color-yellow: oklch(0.52 0.1 85);
309
+ --lt-color-green: oklch(0.52 0.13 152);
310
+ --lt-color-blue: oklch(0.54 0.17 252);
311
+ --lt-color-purple: oklch(0.53 0.19 305);
312
+ }
313
+
314
+ [data-theme="dark"],
315
+ .dark {
316
+ --lt-color-red: oklch(0.83 0.11 27);
317
+ --lt-color-orange: oklch(0.84 0.1 65);
318
+ --lt-color-yellow: oklch(0.87 0.11 100);
319
+ --lt-color-green: oklch(0.85 0.13 155);
320
+ --lt-color-blue: oklch(0.84 0.11 250);
321
+ --lt-color-purple: oklch(0.85 0.11 305);
322
+ }
323
+
302
324
  .lt-cell-badge {
303
325
  display: inline-flex;
304
326
  align-items: center;
@@ -308,67 +330,98 @@
308
330
  font-size: 0.75rem;
309
331
  line-height: 1rem;
310
332
  font-weight: 500;
311
- background-color: var(--lt-cell-bg, var(--lt-muted));
312
- color: var(--lt-cell-fg, var(--lt-muted-fg));
333
+ background-color: var(--lt-tone-bg, var(--lt-muted));
334
+ color: var(--lt-tone-fg, var(--lt-muted-fg));
313
335
  }
314
336
 
315
337
  .lt-cell-icon {
316
338
  display: inline-flex;
317
- color: var(--lt-cell-fg, var(--lt-fg));
339
+ color: var(--lt-tone-fg, var(--lt-fg));
340
+ }
341
+
342
+ .lt-tone-gray {
343
+ --lt-tone-bg: var(--lt-muted);
344
+ --lt-tone-fg: var(--lt-color-gray);
345
+ }
346
+ .lt-tone-red {
347
+ --lt-tone-bg: oklch(0.94 0.03 25);
348
+ --lt-tone-fg: var(--lt-color-red);
349
+ }
350
+ .lt-tone-orange {
351
+ --lt-tone-bg: oklch(0.95 0.04 65);
352
+ --lt-tone-fg: var(--lt-color-orange);
353
+ }
354
+ .lt-tone-yellow {
355
+ --lt-tone-bg: oklch(0.96 0.05 100);
356
+ --lt-tone-fg: var(--lt-color-yellow);
357
+ }
358
+ .lt-tone-green {
359
+ --lt-tone-bg: oklch(0.95 0.05 155);
360
+ --lt-tone-fg: var(--lt-color-green);
361
+ }
362
+ .lt-tone-blue {
363
+ --lt-tone-bg: oklch(0.95 0.03 245);
364
+ --lt-tone-fg: var(--lt-color-blue);
365
+ }
366
+ .lt-tone-purple {
367
+ --lt-tone-bg: oklch(0.95 0.03 305);
368
+ --lt-tone-fg: var(--lt-color-purple);
318
369
  }
319
370
 
320
- .lt-cell-tone-gray {
321
- --lt-cell-bg: var(--lt-muted);
322
- --lt-cell-fg: var(--lt-muted-fg);
371
+ .lt-tone-default,
372
+ .lt-tone-primary,
373
+ .lt-tone-success,
374
+ .lt-tone-info,
375
+ .lt-tone-warning,
376
+ .lt-tone-danger {
377
+ --lt-tone-bg: color-mix(in oklab, var(--lt-tone-fg) 12%, transparent);
323
378
  }
324
- .lt-cell-tone-red {
325
- --lt-cell-bg: oklch(0.94 0.03 25);
326
- --lt-cell-fg: oklch(0.51 0.19 27);
379
+ .lt-tone-default {
380
+ --lt-tone-fg: var(--lt-color-default);
327
381
  }
328
- .lt-cell-tone-orange {
329
- --lt-cell-bg: oklch(0.95 0.04 65);
330
- --lt-cell-fg: oklch(0.55 0.14 55);
382
+ .lt-tone-muted {
383
+ --lt-tone-bg: var(--lt-muted);
384
+ --lt-tone-fg: var(--lt-color-muted);
331
385
  }
332
- .lt-cell-tone-yellow {
333
- --lt-cell-bg: oklch(0.96 0.05 100);
334
- --lt-cell-fg: oklch(0.52 0.1 85);
386
+ .lt-tone-primary {
387
+ --lt-tone-fg: var(--lt-color-primary);
335
388
  }
336
- .lt-cell-tone-green {
337
- --lt-cell-bg: oklch(0.95 0.05 155);
338
- --lt-cell-fg: oklch(0.52 0.13 152);
389
+ .lt-tone-success {
390
+ --lt-tone-fg: var(--lt-color-success);
339
391
  }
340
- .lt-cell-tone-blue {
341
- --lt-cell-bg: oklch(0.95 0.03 245);
342
- --lt-cell-fg: oklch(0.54 0.17 252);
392
+ .lt-tone-info {
393
+ --lt-tone-fg: var(--lt-color-info);
343
394
  }
344
- .lt-cell-tone-purple {
345
- --lt-cell-bg: oklch(0.95 0.03 305);
346
- --lt-cell-fg: oklch(0.53 0.19 305);
395
+ .lt-tone-warning {
396
+ --lt-tone-fg: var(--lt-color-warning);
397
+ }
398
+ .lt-tone-danger {
399
+ --lt-tone-fg: var(--lt-color-danger);
347
400
  }
348
401
 
349
- .dark .lt-cell-tone-red {
350
- --lt-cell-bg: oklch(0.29 0.08 27);
351
- --lt-cell-fg: oklch(0.83 0.11 27);
402
+ [data-theme="dark"] .lt-tone-red,
403
+ .dark .lt-tone-red {
404
+ --lt-tone-bg: oklch(0.29 0.08 27);
352
405
  }
353
- .dark .lt-cell-tone-orange {
354
- --lt-cell-bg: oklch(0.3 0.07 65);
355
- --lt-cell-fg: oklch(0.84 0.1 65);
406
+ [data-theme="dark"] .lt-tone-orange,
407
+ .dark .lt-tone-orange {
408
+ --lt-tone-bg: oklch(0.3 0.07 65);
356
409
  }
357
- .dark .lt-cell-tone-yellow {
358
- --lt-cell-bg: oklch(0.31 0.06 100);
359
- --lt-cell-fg: oklch(0.87 0.11 100);
410
+ [data-theme="dark"] .lt-tone-yellow,
411
+ .dark .lt-tone-yellow {
412
+ --lt-tone-bg: oklch(0.31 0.06 100);
360
413
  }
361
- .dark .lt-cell-tone-green {
362
- --lt-cell-bg: oklch(0.3 0.07 155);
363
- --lt-cell-fg: oklch(0.85 0.13 155);
414
+ [data-theme="dark"] .lt-tone-green,
415
+ .dark .lt-tone-green {
416
+ --lt-tone-bg: oklch(0.3 0.07 155);
364
417
  }
365
- .dark .lt-cell-tone-blue {
366
- --lt-cell-bg: oklch(0.3 0.07 245);
367
- --lt-cell-fg: oklch(0.84 0.11 250);
418
+ [data-theme="dark"] .lt-tone-blue,
419
+ .dark .lt-tone-blue {
420
+ --lt-tone-bg: oklch(0.3 0.07 245);
368
421
  }
369
- .dark .lt-cell-tone-purple {
370
- --lt-cell-bg: oklch(0.3 0.07 305);
371
- --lt-cell-fg: oklch(0.85 0.11 305);
422
+ [data-theme="dark"] .lt-tone-purple,
423
+ .dark .lt-tone-purple {
424
+ --lt-tone-bg: oklch(0.3 0.07 305);
372
425
  }
373
426
 
374
427
  /*
@@ -402,6 +455,15 @@
402
455
  margin: calc(var(--spacing) * 2) 0;
403
456
  }
404
457
 
458
+ /* TipTap renders the empty-editor placeholder via this attribute hook. */
459
+ .lattice-prose :where(p.is-editor-empty:first-child)::before {
460
+ content: attr(data-placeholder);
461
+ color: var(--lt-muted-fg);
462
+ float: left;
463
+ height: 0;
464
+ pointer-events: none;
465
+ }
466
+
405
467
  .lattice-prose :where(ul) {
406
468
  list-style: disc;
407
469
  padding-left: calc(var(--spacing) * 6);
@@ -1,13 +1,15 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { nodeIdentity } from "../../core/test-id.js";
2
3
  import { Link, usePage } from "@inertiajs/react";
3
4
  import { Fragment } from "react";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  //#region resources/js/layout/components/breadcrumbs.tsx
6
7
  var BreadcrumbsComponent = ({ node }) => {
8
+ const { t } = useT("lattice");
7
9
  const crumbs = usePage().props.lattice?.breadcrumbs ?? [];
8
10
  if (crumbs.length === 0) return null;
9
11
  return /* @__PURE__ */ jsx("nav", {
10
- "aria-label": "Breadcrumb",
12
+ "aria-label": t("common.breadcrumb", "Breadcrumb"),
11
13
  "data-lattice-component": nodeIdentity(node),
12
14
  children: /* @__PURE__ */ jsx("ol", {
13
15
  className: "flex items-center gap-2 text-sm text-lt-muted-fg",
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumbs.js","names":[],"sources":["../../../resources/js/layout/components/breadcrumbs.tsx"],"sourcesContent":["import { Link, usePage } from \"@inertiajs/react\";\nimport { Fragment } from \"react\";\nimport type { PagePayload, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\n\nconst BreadcrumbsComponent: RendererComponent<\"breadcrumbs\"> = ({ node }) => {\n const page = usePage();\n const crumbs = (page.props.lattice as PagePayload | undefined)?.breadcrumbs ?? [];\n\n if (crumbs.length === 0) {\n return null;\n }\n\n return (\n <nav aria-label=\"Breadcrumb\" data-lattice-component={nodeIdentity(node)}>\n <ol className=\"flex items-center gap-2 text-sm text-lt-muted-fg\">\n {crumbs.map((crumb, index) => {\n const isLast = index === crumbs.length - 1;\n\n return (\n <Fragment key={crumb.href}>\n <li>\n {isLast ? (\n <span aria-current=\"page\" className=\"text-lt-fg\">\n {crumb.title}\n </span>\n ) : (\n <Link className=\"hover:text-lt-fg\" href={crumb.href}>\n {crumb.title}\n </Link>\n )}\n </li>\n {isLast ? null : <li aria-hidden=\"true\">/</li>}\n </Fragment>\n );\n })}\n </ol>\n </nav>\n );\n};\n\nexport default BreadcrumbsComponent;\n"],"mappings":";;;;;AAKA,IAAM,wBAA0D,EAAE,WAAW;CAE3E,MAAM,SADO,QACG,EAAK,MAAM,SAAqC,eAAe,CAAC;CAEhF,IAAI,OAAO,WAAW,GACpB,OAAO;CAGT,OACE,oBAAC,OAAD;EAAK,cAAW;EAAa,0BAAwB,aAAa,IAAI;YACpE,oBAAC,MAAD;GAAI,WAAU;aACX,OAAO,KAAK,OAAO,UAAU;IAC5B,MAAM,SAAS,UAAU,OAAO,SAAS;IAEzC,OACE,qBAAC,UAAD,EAAA,UAAA,CACE,oBAAC,MAAD,EAAA,UACG,SACC,oBAAC,QAAD;KAAM,gBAAa;KAAO,WAAU;eACjC,MAAM;IACH,CAAA,IAEN,oBAAC,MAAD;KAAM,WAAU;KAAmB,MAAM,MAAM;eAC5C,MAAM;IACH,CAAA,EAEN,CAAA,GACH,SAAS,OAAO,oBAAC,MAAD;KAAI,eAAY;eAAO;IAAK,CAAA,CACrC,EAAA,GAbK,MAAM,IAaX;GAEd,CAAC;EACC,CAAA;CACD,CAAA;AAET"}
1
+ {"version":3,"file":"breadcrumbs.js","names":[],"sources":["../../../resources/js/layout/components/breadcrumbs.tsx"],"sourcesContent":["import { Link, usePage } from \"@inertiajs/react\";\nimport { Fragment } from \"react\";\nimport type { PagePayload, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\n\nconst BreadcrumbsComponent: RendererComponent<\"breadcrumbs\"> = ({ node }) => {\n const { t } = useT(\"lattice\");\n const page = usePage();\n const crumbs = (page.props.lattice as PagePayload | undefined)?.breadcrumbs ?? [];\n\n if (crumbs.length === 0) {\n return null;\n }\n\n return (\n <nav\n aria-label={t(\"common.breadcrumb\", \"Breadcrumb\")}\n data-lattice-component={nodeIdentity(node)}\n >\n <ol className=\"flex items-center gap-2 text-sm text-lt-muted-fg\">\n {crumbs.map((crumb, index) => {\n const isLast = index === crumbs.length - 1;\n\n return (\n <Fragment key={crumb.href}>\n <li>\n {isLast ? (\n <span aria-current=\"page\" className=\"text-lt-fg\">\n {crumb.title}\n </span>\n ) : (\n <Link className=\"hover:text-lt-fg\" href={crumb.href}>\n {crumb.title}\n </Link>\n )}\n </li>\n {isLast ? null : <li aria-hidden=\"true\">/</li>}\n </Fragment>\n );\n })}\n </ol>\n </nav>\n );\n};\n\nexport default BreadcrumbsComponent;\n"],"mappings":";;;;;;AAMA,IAAM,wBAA0D,EAAE,WAAW;CAC3E,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,MAAM,SADO,QACG,EAAK,MAAM,SAAqC,eAAe,CAAC;CAEhF,IAAI,OAAO,WAAW,GACpB,OAAO;CAGT,OACE,oBAAC,OAAD;EACE,cAAY,EAAE,qBAAqB,YAAY;EAC/C,0BAAwB,aAAa,IAAI;YAEzC,oBAAC,MAAD;GAAI,WAAU;aACX,OAAO,KAAK,OAAO,UAAU;IAC5B,MAAM,SAAS,UAAU,OAAO,SAAS;IAEzC,OACE,qBAAC,UAAD,EAAA,UAAA,CACE,oBAAC,MAAD,EAAA,UACG,SACC,oBAAC,QAAD;KAAM,gBAAa;KAAO,WAAU;eACjC,MAAM;IACH,CAAA,IAEN,oBAAC,MAAD;KAAM,WAAU;KAAmB,MAAM,MAAM;eAC5C,MAAM;IACH,CAAA,EAEN,CAAA,GACH,SAAS,OAAO,oBAAC,MAAD;KAAI,eAAY;eAAO;IAAK,CAAA,CACrC,EAAA,GAbK,MAAM,IAaX;GAEd,CAAC;EACC,CAAA;CACD,CAAA;AAET"}
@@ -1,7 +1,7 @@
1
+ import { onCallout } from "../../toast/callout.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { Icon } from "../../icons/sprite.js";
3
4
  import { RenderNode } from "../../core/renderer.js";
4
- import { onCallout } from "../../toast/callout.js";
5
5
  import { useT } from "../../i18n/instance.js";
6
6
  import { variantStyles } from "../../toast/variant-styles.js";
7
7
  import { useEffect, useState } from "react";
@@ -0,0 +1,9 @@
1
+ import { CSSProperties } from 'react';
2
+ import { Color, ColorName } from '../types/generated.js';
3
+ export declare function namedColor(value: ColorName): Color;
4
+ export declare function coerceColor(value: unknown): Color | undefined;
5
+ export declare function colorValue(color: Color): string;
6
+ export declare function toneProps(color: Color): {
7
+ className?: string;
8
+ style?: CSSProperties;
9
+ };