@lattice-php/lattice 0.9.0 → 0.11.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 (91) hide show
  1. package/dist/action/components/action-form.js +1 -1
  2. package/dist/action/components/action-form.js.map +1 -1
  3. package/dist/chat/components/chat-box.js +1 -1
  4. package/dist/chat/components/chat-box.js.map +1 -1
  5. package/dist/chat/components/prompt-input.js +2 -2
  6. package/dist/chat/components/prompt-input.js.map +1 -1
  7. package/dist/core/components/combobox.js +1 -1
  8. package/dist/core/components/combobox.js.map +1 -1
  9. package/dist/core/components/fragment.js +4 -1
  10. package/dist/core/components/fragment.js.map +1 -1
  11. package/dist/core/components/icon.js +4 -1
  12. package/dist/core/components/icon.js.map +1 -1
  13. package/dist/core/components/info-tooltip.js +1 -1
  14. package/dist/core/components/info-tooltip.js.map +1 -1
  15. package/dist/core/components/spinner.js +1 -1
  16. package/dist/core/components/spinner.js.map +1 -1
  17. package/dist/core/components/tabs.js +1 -1
  18. package/dist/core/components/tabs.js.map +1 -1
  19. package/dist/core/components/text.js +4 -1
  20. package/dist/core/components/text.js.map +1 -1
  21. package/dist/form/components/fields/date-input.js +7 -6
  22. package/dist/form/components/fields/date-input.js.map +1 -1
  23. package/dist/form/components/fields/date-picker-control.d.ts +18 -0
  24. package/dist/form/components/fields/date-picker-control.js +199 -0
  25. package/dist/form/components/fields/date-picker-control.js.map +1 -0
  26. package/dist/form/components/fields/date-picker-value.d.ts +10 -0
  27. package/dist/form/components/fields/date-picker-value.js +125 -0
  28. package/dist/form/components/fields/date-picker-value.js.map +1 -0
  29. package/dist/form/components/fields/date-time-input.d.ts +2 -0
  30. package/dist/form/components/fields/date-time-input.js +34 -0
  31. package/dist/form/components/fields/date-time-input.js.map +1 -0
  32. package/dist/form/components/fields/file-upload.js +3 -3
  33. package/dist/form/components/fields/file-upload.js.map +1 -1
  34. package/dist/form/components/fields/lazy-date-picker-control.d.ts +2 -0
  35. package/dist/form/components/fields/lazy-date-picker-control.js +17 -0
  36. package/dist/form/components/fields/lazy-date-picker-control.js.map +1 -0
  37. package/dist/form/components/fields/number-input.js +1 -1
  38. package/dist/form/components/fields/rich-editor.js +3 -3
  39. package/dist/form/components/fields/rich-editor.js.map +1 -1
  40. package/dist/form/components/fields/row-action-menu.js +2 -2
  41. package/dist/form/components/fields/row-action-menu.js.map +1 -1
  42. package/dist/form/components/fields/select.js +1 -1
  43. package/dist/form/components/fields/select.js.map +1 -1
  44. package/dist/form/components/fields/table-rows.js +2 -2
  45. package/dist/form/components/fields/table-rows.js.map +1 -1
  46. package/dist/form/components/fields/text-input.js +1 -1
  47. package/dist/form/components/fields/time-input.d.ts +2 -0
  48. package/dist/form/components/fields/time-input.js +30 -0
  49. package/dist/form/components/fields/time-input.js.map +1 -0
  50. package/dist/form/components/fields/toggle.d.ts +2 -0
  51. package/dist/form/components/fields/toggle.js +65 -0
  52. package/dist/form/components/fields/toggle.js.map +1 -0
  53. package/dist/form/components/index.d.ts +3 -0
  54. package/dist/form/components/index.js +4 -1
  55. package/dist/form/components/types.d.ts +1 -1
  56. package/dist/form/components/use-controlled-field.d.ts +2 -0
  57. package/dist/form/components/use-controlled-field.js +6 -2
  58. package/dist/form/components/use-controlled-field.js.map +1 -1
  59. package/dist/form/index.js +4 -1
  60. package/dist/form/index.js.map +1 -1
  61. package/dist/lattice.css +6 -0
  62. package/dist/layout/callouts.js +1 -1
  63. package/dist/layout/callouts.js.map +1 -1
  64. package/dist/lib/utils.js +11 -1
  65. package/dist/lib/utils.js.map +1 -1
  66. package/dist/remote/components/data-list.js +3 -3
  67. package/dist/remote/components/data-list.js.map +1 -1
  68. package/dist/table/components/bulk-bar.js +2 -2
  69. package/dist/table/components/bulk-bar.js.map +1 -1
  70. package/dist/table/components/column-filter-control.js +5 -5
  71. package/dist/table/components/column-filter-control.js.map +1 -1
  72. package/dist/table/components/filter-bar.js +3 -3
  73. package/dist/table/components/filter-bar.js.map +1 -1
  74. package/dist/table/components/filter-controls.js +9 -9
  75. package/dist/table/components/filter-controls.js.map +1 -1
  76. package/dist/table/components/filter-stack-bar.js +1 -1
  77. package/dist/table/components/filter-stack-bar.js.map +1 -1
  78. package/dist/table/components/filter-value-input.js +5 -5
  79. package/dist/table/components/filter-value-input.js.map +1 -1
  80. package/dist/table/components/pagination.js +8 -8
  81. package/dist/table/components/pagination.js.map +1 -1
  82. package/dist/table/components/table.js +4 -4
  83. package/dist/table/components/table.js.map +1 -1
  84. package/dist/table/query.js +1 -1
  85. package/dist/table/query.js.map +1 -1
  86. package/dist/toast/toaster.js +1 -1
  87. package/dist/toast/toaster.js.map +1 -1
  88. package/dist/types/generated.d.ts +97 -2
  89. package/package.json +8 -2
  90. package/resources/icons/calendar.svg +18 -0
  91. package/resources/icons/chevron-left.svg +15 -0
@@ -218,7 +218,7 @@ function ActionForm({ description, formNode, onClose, title, ...rest }) {
218
218
  ...description ? {} : { "aria-describedby": void 0 },
219
219
  className: "max-h-[min(680px,calc(100vh-2rem))] w-full max-w-lg overflow-y-auto",
220
220
  children: [/* @__PURE__ */ jsx(DialogHeader, {
221
- closeLabel: t("a11y.close", "Close"),
221
+ closeLabel: t("common.close", "Close"),
222
222
  description,
223
223
  title
224
224
  }), /* @__PURE__ */ jsx("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"action-form.js","names":[],"sources":["../../../resources/js/action/components/action-form.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { apiFetch } from \"@lattice-php/lattice/core/api\";\nimport { Button } from \"@lattice-php/lattice/core/components/button\";\nimport { Dialog, DialogContent, DialogHeader } from \"@lattice-php/lattice/core/components/dialog\";\nimport { Skeleton } from \"@lattice-php/lattice/core/components/skeleton\";\nimport { Spinner } from \"@lattice-php/lattice/core/components/spinner\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport { FormProvider } from \"@lattice-php/lattice/form/components/context\";\nimport { walkFields } from \"@lattice-php/lattice/form/components/field-props\";\nimport { FORM_DEBOUNCE_MS } from \"@lattice-php/lattice/form/components/form-transport\";\nimport { PrefillProvider } from \"@lattice-php/lattice/form/components/prefill-context\";\nimport { ResolvedNodesProvider } from \"@lattice-php/lattice/form/components/resolved-nodes\";\nimport { useFormResolver } from \"@lattice-php/lattice/form/components/use-form-resolver\";\nimport { FormValuesProvider, useFormValues } from \"@lattice-php/lattice/form/components/values\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { dispatchActionError } from \"@lattice-php/lattice/effects/dispatch\";\nimport type { ActionResponse } from \"@lattice-php/lattice/effects/dispatch\";\n\ntype FieldErrors = Record<string, string | undefined>;\n\ntype ActionFormProps = {\n cancelLabel: string;\n componentRef: string;\n description?: string;\n endpoint: string;\n /** Extra payload merged into every request, e.g. a bulk action's selection. */\n extraData?: Record<string, unknown>;\n /** The form to render; null while a lazy schema is still being fetched. */\n formNode: Node | null;\n method: string;\n onClose: () => void;\n onSuccess: (response: ActionResponse) => void;\n submitLabel: string;\n title: string;\n};\n\n/**\n * Fetch a lazily-served form schema from the action endpoint while `enabled`,\n * so it can be prefilled per record. Returns null until it arrives.\n */\nexport function useLazyActionForm(\n endpoint: string,\n componentRef: string,\n enabled: boolean,\n): Node | null {\n const [node, setNode] = useState<Node | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n setNode(null);\n\n return;\n }\n\n const controller = new AbortController();\n\n void apiFetch(endpoint, {\n body: JSON.stringify({ _form: true }),\n ref: componentRef,\n method: \"POST\",\n signal: controller.signal,\n throwOnError: false,\n })\n .then((response) => (response.ok ? (response.json() as Promise<Node>) : null))\n .then((fetched) => setNode(fetched))\n .catch(() => {});\n\n return () => controller.abort();\n }, [enabled, endpoint, componentRef]);\n\n return node;\n}\n\nfunction firstErrors(errors: Record<string, string[] | string> | undefined): FieldErrors {\n const result: FieldErrors = {};\n\n for (const [key, value] of Object.entries(errors ?? {})) {\n result[key] = Array.isArray(value) ? value[0] : value;\n }\n\n return result;\n}\n\nfunction ActionFormSkeleton() {\n return (\n <div className=\"space-y-4\" data-lattice-action-form-loading>\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n );\n}\n\ntype CollectedFields = {\n labels: Record<string, string>;\n values: Record<string, unknown>;\n};\n\nfunction collectFields(formNode: Node): CollectedFields {\n const labels: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n\n walkFields(formNode.schema, (props) => {\n if (!props.name) {\n return;\n }\n if (props.label) {\n labels[props.name] = props.label;\n }\n if (props.value !== undefined) {\n values[props.name] = props.value;\n }\n });\n\n return {\n labels,\n values: { ...values, ...(formNode.props?.state as Record<string, unknown> | undefined) },\n };\n}\n\nfunction ActionFormBody({\n cancelLabel,\n componentRef,\n endpoint,\n extraData,\n fieldLabels,\n formNode,\n method,\n onClose,\n onSuccess,\n precognitive,\n submitLabel,\n}: Omit<ActionFormProps, \"description\" | \"title\"> & {\n fieldLabels: Record<string, string>;\n formNode: Node;\n precognitive: boolean;\n}) {\n const values = useFormValues();\n const valuesRef = useRef(values);\n valuesRef.current = values;\n const extraDataRef = useRef(extraData);\n extraDataRef.current = extraData;\n const { nodes: resolvedNodes, markUserEdit } = useFormResolver(\n endpoint,\n componentRef,\n formNode.schema,\n );\n\n const [errors, setErrors] = useState<FieldErrors>({});\n const [processing, setProcessing] = useState(false);\n const timer = useRef<number | undefined>(undefined);\n\n const request = useCallback(\n (extraHeaders?: Record<string, string>): Promise<Response> =>\n apiFetch(endpoint, {\n body: JSON.stringify({ ...valuesRef.current, ...extraDataRef.current }),\n method,\n ref: componentRef,\n headers: extraHeaders,\n throwOnError: false,\n }),\n [componentRef, endpoint, method],\n );\n\n const clearErrors = useCallback((field: string) => {\n setErrors((current) =>\n current[field] === undefined ? current : { ...current, [field]: undefined },\n );\n }, []);\n\n const validate = useCallback(\n (field: string) => {\n if (!precognitive) {\n return;\n }\n\n window.clearTimeout(timer.current);\n timer.current = window.setTimeout(() => {\n void request({ Precognition: \"true\", \"Precognition-Validate-Only\": field })\n .then(async (response) => {\n if (response.status === 422) {\n const body = (await response.json()) as { errors?: Record<string, string[]> };\n setErrors((current) => ({ ...current, ...firstErrors(body.errors) }));\n\n return;\n }\n\n clearErrors(field);\n })\n .catch(() => {});\n }, FORM_DEBOUNCE_MS);\n },\n [clearErrors, precognitive, request],\n );\n\n const submit = useCallback(() => {\n setProcessing(true);\n\n void request()\n .then(async (response) => {\n if (response.status === 422) {\n const body = (await response.json()) as { errors?: Record<string, string[]> };\n setErrors(firstErrors(body.errors));\n\n return;\n }\n\n if (!response.ok) {\n dispatchActionError(new Error(`Action request failed with status ${response.status}`));\n\n return;\n }\n\n onSuccess((await response.json()) as ActionResponse);\n })\n .catch((error: unknown) => dispatchActionError(error))\n .finally(() => setProcessing(false));\n }, [onSuccess, request]);\n\n const context = useMemo(\n () => ({\n action: endpoint,\n clearErrors,\n componentRef,\n errors,\n fieldLabels,\n precognitive,\n processing,\n validate,\n }),\n [clearErrors, componentRef, endpoint, errors, fieldLabels, precognitive, processing, validate],\n );\n\n return (\n <FormProvider value={context}>\n <form\n className=\"flex flex-col gap-6\"\n onSubmit={(event) => {\n event.preventDefault();\n submit();\n }}\n >\n <PrefillProvider value={{ markUserEdit }}>\n <ResolvedNodesProvider nodes={resolvedNodes}>\n <Renderer nodes={formNode.schema ?? []} />\n </ResolvedNodesProvider>\n </PrefillProvider>\n\n <div className=\"flex justify-end gap-3\">\n <Button\n data-test=\"action-form-cancel\"\n disabled={processing}\n onClick={onClose}\n type=\"button\"\n variant=\"ghost\"\n >\n {cancelLabel}\n </Button>\n\n <Button data-test=\"action-form-submit\" disabled={processing} type=\"submit\">\n {processing && <Spinner />}\n {submitLabel}\n </Button>\n </div>\n </form>\n </FormProvider>\n );\n}\n\nfunction ActionFormContent({\n formNode,\n ...rest\n}: Omit<ActionFormProps, \"description\" | \"title\"> & { formNode: Node }) {\n const precognitive = Boolean(formNode.props?.precognitive);\n const { labels: fieldLabels, values: initialValues } = useMemo(\n () => collectFields(formNode),\n [formNode],\n );\n\n return (\n <FormValuesProvider initial={initialValues}>\n <ActionFormBody\n fieldLabels={fieldLabels}\n formNode={formNode}\n precognitive={precognitive}\n {...rest}\n />\n </FormValuesProvider>\n );\n}\n\nexport function ActionForm({ description, formNode, onClose, title, ...rest }: ActionFormProps) {\n const { t } = useT(\"lattice\");\n\n return (\n <Dialog\n open\n onOpenChange={(open) => {\n if (!open) {\n onClose();\n }\n }}\n >\n <DialogContent\n {...(description ? {} : { \"aria-describedby\": undefined })}\n className=\"max-h-[min(680px,calc(100vh-2rem))] w-full max-w-lg overflow-y-auto\"\n >\n <DialogHeader\n closeLabel={t(\"a11y.close\", \"Close\")}\n description={description}\n title={title}\n />\n\n <div className=\"mt-6\">\n {formNode ? (\n <ActionFormContent formNode={formNode} onClose={onClose} {...rest} />\n ) : (\n <ActionFormSkeleton />\n )}\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"action-form.js","names":[],"sources":["../../../resources/js/action/components/action-form.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { apiFetch } from \"@lattice-php/lattice/core/api\";\nimport { Button } from \"@lattice-php/lattice/core/components/button\";\nimport { Dialog, DialogContent, DialogHeader } from \"@lattice-php/lattice/core/components/dialog\";\nimport { Skeleton } from \"@lattice-php/lattice/core/components/skeleton\";\nimport { Spinner } from \"@lattice-php/lattice/core/components/spinner\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport { FormProvider } from \"@lattice-php/lattice/form/components/context\";\nimport { walkFields } from \"@lattice-php/lattice/form/components/field-props\";\nimport { FORM_DEBOUNCE_MS } from \"@lattice-php/lattice/form/components/form-transport\";\nimport { PrefillProvider } from \"@lattice-php/lattice/form/components/prefill-context\";\nimport { ResolvedNodesProvider } from \"@lattice-php/lattice/form/components/resolved-nodes\";\nimport { useFormResolver } from \"@lattice-php/lattice/form/components/use-form-resolver\";\nimport { FormValuesProvider, useFormValues } from \"@lattice-php/lattice/form/components/values\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { dispatchActionError } from \"@lattice-php/lattice/effects/dispatch\";\nimport type { ActionResponse } from \"@lattice-php/lattice/effects/dispatch\";\n\ntype FieldErrors = Record<string, string | undefined>;\n\ntype ActionFormProps = {\n cancelLabel: string;\n componentRef: string;\n description?: string;\n endpoint: string;\n /** Extra payload merged into every request, e.g. a bulk action's selection. */\n extraData?: Record<string, unknown>;\n /** The form to render; null while a lazy schema is still being fetched. */\n formNode: Node | null;\n method: string;\n onClose: () => void;\n onSuccess: (response: ActionResponse) => void;\n submitLabel: string;\n title: string;\n};\n\n/**\n * Fetch a lazily-served form schema from the action endpoint while `enabled`,\n * so it can be prefilled per record. Returns null until it arrives.\n */\nexport function useLazyActionForm(\n endpoint: string,\n componentRef: string,\n enabled: boolean,\n): Node | null {\n const [node, setNode] = useState<Node | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n setNode(null);\n\n return;\n }\n\n const controller = new AbortController();\n\n void apiFetch(endpoint, {\n body: JSON.stringify({ _form: true }),\n ref: componentRef,\n method: \"POST\",\n signal: controller.signal,\n throwOnError: false,\n })\n .then((response) => (response.ok ? (response.json() as Promise<Node>) : null))\n .then((fetched) => setNode(fetched))\n .catch(() => {});\n\n return () => controller.abort();\n }, [enabled, endpoint, componentRef]);\n\n return node;\n}\n\nfunction firstErrors(errors: Record<string, string[] | string> | undefined): FieldErrors {\n const result: FieldErrors = {};\n\n for (const [key, value] of Object.entries(errors ?? {})) {\n result[key] = Array.isArray(value) ? value[0] : value;\n }\n\n return result;\n}\n\nfunction ActionFormSkeleton() {\n return (\n <div className=\"space-y-4\" data-lattice-action-form-loading>\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n );\n}\n\ntype CollectedFields = {\n labels: Record<string, string>;\n values: Record<string, unknown>;\n};\n\nfunction collectFields(formNode: Node): CollectedFields {\n const labels: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n\n walkFields(formNode.schema, (props) => {\n if (!props.name) {\n return;\n }\n if (props.label) {\n labels[props.name] = props.label;\n }\n if (props.value !== undefined) {\n values[props.name] = props.value;\n }\n });\n\n return {\n labels,\n values: { ...values, ...(formNode.props?.state as Record<string, unknown> | undefined) },\n };\n}\n\nfunction ActionFormBody({\n cancelLabel,\n componentRef,\n endpoint,\n extraData,\n fieldLabels,\n formNode,\n method,\n onClose,\n onSuccess,\n precognitive,\n submitLabel,\n}: Omit<ActionFormProps, \"description\" | \"title\"> & {\n fieldLabels: Record<string, string>;\n formNode: Node;\n precognitive: boolean;\n}) {\n const values = useFormValues();\n const valuesRef = useRef(values);\n valuesRef.current = values;\n const extraDataRef = useRef(extraData);\n extraDataRef.current = extraData;\n const { nodes: resolvedNodes, markUserEdit } = useFormResolver(\n endpoint,\n componentRef,\n formNode.schema,\n );\n\n const [errors, setErrors] = useState<FieldErrors>({});\n const [processing, setProcessing] = useState(false);\n const timer = useRef<number | undefined>(undefined);\n\n const request = useCallback(\n (extraHeaders?: Record<string, string>): Promise<Response> =>\n apiFetch(endpoint, {\n body: JSON.stringify({ ...valuesRef.current, ...extraDataRef.current }),\n method,\n ref: componentRef,\n headers: extraHeaders,\n throwOnError: false,\n }),\n [componentRef, endpoint, method],\n );\n\n const clearErrors = useCallback((field: string) => {\n setErrors((current) =>\n current[field] === undefined ? current : { ...current, [field]: undefined },\n );\n }, []);\n\n const validate = useCallback(\n (field: string) => {\n if (!precognitive) {\n return;\n }\n\n window.clearTimeout(timer.current);\n timer.current = window.setTimeout(() => {\n void request({ Precognition: \"true\", \"Precognition-Validate-Only\": field })\n .then(async (response) => {\n if (response.status === 422) {\n const body = (await response.json()) as { errors?: Record<string, string[]> };\n setErrors((current) => ({ ...current, ...firstErrors(body.errors) }));\n\n return;\n }\n\n clearErrors(field);\n })\n .catch(() => {});\n }, FORM_DEBOUNCE_MS);\n },\n [clearErrors, precognitive, request],\n );\n\n const submit = useCallback(() => {\n setProcessing(true);\n\n void request()\n .then(async (response) => {\n if (response.status === 422) {\n const body = (await response.json()) as { errors?: Record<string, string[]> };\n setErrors(firstErrors(body.errors));\n\n return;\n }\n\n if (!response.ok) {\n dispatchActionError(new Error(`Action request failed with status ${response.status}`));\n\n return;\n }\n\n onSuccess((await response.json()) as ActionResponse);\n })\n .catch((error: unknown) => dispatchActionError(error))\n .finally(() => setProcessing(false));\n }, [onSuccess, request]);\n\n const context = useMemo(\n () => ({\n action: endpoint,\n clearErrors,\n componentRef,\n errors,\n fieldLabels,\n precognitive,\n processing,\n validate,\n }),\n [clearErrors, componentRef, endpoint, errors, fieldLabels, precognitive, processing, validate],\n );\n\n return (\n <FormProvider value={context}>\n <form\n className=\"flex flex-col gap-6\"\n onSubmit={(event) => {\n event.preventDefault();\n submit();\n }}\n >\n <PrefillProvider value={{ markUserEdit }}>\n <ResolvedNodesProvider nodes={resolvedNodes}>\n <Renderer nodes={formNode.schema ?? []} />\n </ResolvedNodesProvider>\n </PrefillProvider>\n\n <div className=\"flex justify-end gap-3\">\n <Button\n data-test=\"action-form-cancel\"\n disabled={processing}\n onClick={onClose}\n type=\"button\"\n variant=\"ghost\"\n >\n {cancelLabel}\n </Button>\n\n <Button data-test=\"action-form-submit\" disabled={processing} type=\"submit\">\n {processing && <Spinner />}\n {submitLabel}\n </Button>\n </div>\n </form>\n </FormProvider>\n );\n}\n\nfunction ActionFormContent({\n formNode,\n ...rest\n}: Omit<ActionFormProps, \"description\" | \"title\"> & { formNode: Node }) {\n const precognitive = Boolean(formNode.props?.precognitive);\n const { labels: fieldLabels, values: initialValues } = useMemo(\n () => collectFields(formNode),\n [formNode],\n );\n\n return (\n <FormValuesProvider initial={initialValues}>\n <ActionFormBody\n fieldLabels={fieldLabels}\n formNode={formNode}\n precognitive={precognitive}\n {...rest}\n />\n </FormValuesProvider>\n );\n}\n\nexport function ActionForm({ description, formNode, onClose, title, ...rest }: ActionFormProps) {\n const { t } = useT(\"lattice\");\n\n return (\n <Dialog\n open\n onOpenChange={(open) => {\n if (!open) {\n onClose();\n }\n }}\n >\n <DialogContent\n {...(description ? {} : { \"aria-describedby\": undefined })}\n className=\"max-h-[min(680px,calc(100vh-2rem))] w-full max-w-lg overflow-y-auto\"\n >\n <DialogHeader\n closeLabel={t(\"common.close\", \"Close\")}\n description={description}\n title={title}\n />\n\n <div className=\"mt-6\">\n {formNode ? (\n <ActionFormContent formNode={formNode} onClose={onClose} {...rest} />\n ) : (\n <ActionFormSkeleton />\n )}\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
@@ -45,7 +45,7 @@ var ChatBox = ({ node }) => {
45
45
  className: "flex items-center border-b border-lt-border px-3 py-2",
46
46
  children: /* @__PURE__ */ jsx("span", {
47
47
  className: "text-sm font-medium text-lt-fg",
48
- children: props.title ?? t("chat.title", "Chat")
48
+ children: props.title ?? t("common.chat.title", "Chat")
49
49
  })
50
50
  }),
51
51
  /* @__PURE__ */ jsx("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"chat-box.js","names":[],"sources":["../../../resources/js/chat/components/chat-box.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { apiFetch, remoteJson } from \"@lattice-php/lattice/core/api\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { ChatBox as ChatBoxProps } from \"@lattice-php/lattice/types/generated\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { createRemoteNdjsonChatTransport, ndjsonChatTransport } from \"../transport\";\nimport { useChat } from \"../use-chat\";\nimport type { ChatMessage } from \"../types\";\nimport { MessageList } from \"./message-list\";\nimport { PromptInput } from \"./prompt-input\";\n\ntype ChatHistoryResponse = { messages: ChatMessage[] };\n\nexport const ChatBox: RendererComponent<\"chat.box\"> = ({ node }) => {\n const props: ChatBoxProps = node.props;\n const { t } = useT(\"lattice\");\n const transport = useMemo(\n () => (props.remote ? createRemoteNdjsonChatTransport(props.remote) : ndjsonChatTransport),\n [props.remote],\n );\n const { messages, status, error, sendMessage, setMessages } = useChat({\n endpoint: props.streamEndpoint ?? \"\",\n transport,\n });\n\n const seededRef = useRef(false);\n\n const seedHistory = useCallback(async (): Promise<void> => {\n if (seededRef.current || !props.historyEndpoint) {\n return;\n }\n\n seededRef.current = true;\n\n if (props.remote) {\n const payload = await remoteJson<ChatHistoryResponse>(props.historyEndpoint, {\n remote: props.remote,\n });\n setMessages(payload.messages);\n\n return;\n }\n\n const response = await apiFetch(props.historyEndpoint, { throwOnError: false });\n\n if (!response.ok) {\n return;\n }\n\n const payload = (await response.json()) as ChatHistoryResponse;\n setMessages(payload.messages);\n }, [props.historyEndpoint, props.remote, setMessages]);\n\n useEffect(() => {\n void seedHistory().catch(() => {});\n }, [seedHistory]);\n\n const busy = status === \"submitted\" || status === \"streaming\";\n const disabled = busy || !props.streamEndpoint;\n\n return (\n <div\n className={cn(\n \"flex flex-col overflow-hidden border border-lt-border bg-lt-bg\",\n props.fill\n ? \"sticky top-0 h-full min-h-[28rem] w-full\"\n : \"h-[28rem] w-80 rounded-lt shadow-lt-lg\",\n )}\n data-test={testIdentity(\"chat-box\")}\n >\n <div className=\"flex items-center border-b border-lt-border px-3 py-2\">\n <span className=\"text-sm font-medium text-lt-fg\">\n {props.title ?? t(\"chat.title\", \"Chat\")}\n </span>\n </div>\n <div className=\"flex-1 overflow-y-auto\">\n <MessageList messages={messages} />\n </div>\n {error ? (\n <div className=\"border-t border-lt-danger/40 px-3 py-2 text-xs text-lt-danger\">{error}</div>\n ) : null}\n <PromptInput\n disabled={disabled}\n onSubmit={sendMessage}\n placeholder={props.placeholder ?? undefined}\n />\n </div>\n );\n};\n\nexport default ChatBox;\n"],"mappings":";;;;;;;;;;;AAeA,IAAa,WAA0C,EAAE,WAAW;CAClE,MAAM,QAAsB,KAAK;CACjC,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,YAAY,cACT,MAAM,SAAS,gCAAgC,MAAM,MAAM,IAAI,qBACtE,CAAC,MAAM,MAAM,CACf;CACA,MAAM,EAAE,UAAU,QAAQ,OAAO,aAAa,gBAAgB,QAAQ;EACpE,UAAU,MAAM,kBAAkB;EAClC;CACF,CAAC;CAED,MAAM,YAAY,OAAO,KAAK;CAE9B,MAAM,cAAc,YAAY,YAA2B;EACzD,IAAI,UAAU,WAAW,CAAC,MAAM,iBAC9B;EAGF,UAAU,UAAU;EAEpB,IAAI,MAAM,QAAQ;GAIhB,aAAY,MAHU,WAAgC,MAAM,iBAAiB,EAC3E,QAAQ,MAAM,OAChB,CAAC,GACmB,QAAQ;GAE5B;EACF;EAEA,MAAM,WAAW,MAAM,SAAS,MAAM,iBAAiB,EAAE,cAAc,MAAM,CAAC;EAE9E,IAAI,CAAC,SAAS,IACZ;EAIF,aAAY,MADW,SAAS,KAAK,GACjB,QAAQ;CAC9B,GAAG;EAAC,MAAM;EAAiB,MAAM;EAAQ;CAAW,CAAC;CAErD,gBAAgB;EACd,YAAiB,EAAE,YAAY,CAAC,CAAC;CACnC,GAAG,CAAC,WAAW,CAAC;CAGhB,MAAM,WADO,WAAW,eAAe,WAAW,eACzB,CAAC,MAAM;CAEhC,OACE,qBAAC,OAAD;EACE,WAAW,GACT,kEACA,MAAM,OACF,6CACA,wCACN;EACA,aAAW,aAAa,UAAU;YAPpC;GASE,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,QAAD;KAAM,WAAU;eACb,MAAM,SAAS,EAAE,cAAc,MAAM;IAClC,CAAA;GACH,CAAA;GACL,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,aAAD,EAAuB,SAAW,CAAA;GAC/B,CAAA;GACJ,QACC,oBAAC,OAAD;IAAK,WAAU;cAAiE;GAAW,CAAA,IACzF;GACJ,oBAAC,aAAD;IACY;IACV,UAAU;IACV,aAAa,MAAM,eAAe,KAAA;GACnC,CAAA;EACE;;AAET"}
1
+ {"version":3,"file":"chat-box.js","names":[],"sources":["../../../resources/js/chat/components/chat-box.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { apiFetch, remoteJson } from \"@lattice-php/lattice/core/api\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { ChatBox as ChatBoxProps } from \"@lattice-php/lattice/types/generated\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { createRemoteNdjsonChatTransport, ndjsonChatTransport } from \"../transport\";\nimport { useChat } from \"../use-chat\";\nimport type { ChatMessage } from \"../types\";\nimport { MessageList } from \"./message-list\";\nimport { PromptInput } from \"./prompt-input\";\n\ntype ChatHistoryResponse = { messages: ChatMessage[] };\n\nexport const ChatBox: RendererComponent<\"chat.box\"> = ({ node }) => {\n const props: ChatBoxProps = node.props;\n const { t } = useT(\"lattice\");\n const transport = useMemo(\n () => (props.remote ? createRemoteNdjsonChatTransport(props.remote) : ndjsonChatTransport),\n [props.remote],\n );\n const { messages, status, error, sendMessage, setMessages } = useChat({\n endpoint: props.streamEndpoint ?? \"\",\n transport,\n });\n\n const seededRef = useRef(false);\n\n const seedHistory = useCallback(async (): Promise<void> => {\n if (seededRef.current || !props.historyEndpoint) {\n return;\n }\n\n seededRef.current = true;\n\n if (props.remote) {\n const payload = await remoteJson<ChatHistoryResponse>(props.historyEndpoint, {\n remote: props.remote,\n });\n setMessages(payload.messages);\n\n return;\n }\n\n const response = await apiFetch(props.historyEndpoint, { throwOnError: false });\n\n if (!response.ok) {\n return;\n }\n\n const payload = (await response.json()) as ChatHistoryResponse;\n setMessages(payload.messages);\n }, [props.historyEndpoint, props.remote, setMessages]);\n\n useEffect(() => {\n void seedHistory().catch(() => {});\n }, [seedHistory]);\n\n const busy = status === \"submitted\" || status === \"streaming\";\n const disabled = busy || !props.streamEndpoint;\n\n return (\n <div\n className={cn(\n \"flex flex-col overflow-hidden border border-lt-border bg-lt-bg\",\n props.fill\n ? \"sticky top-0 h-full min-h-[28rem] w-full\"\n : \"h-[28rem] w-80 rounded-lt shadow-lt-lg\",\n )}\n data-test={testIdentity(\"chat-box\")}\n >\n <div className=\"flex items-center border-b border-lt-border px-3 py-2\">\n <span className=\"text-sm font-medium text-lt-fg\">\n {props.title ?? t(\"common.chat.title\", \"Chat\")}\n </span>\n </div>\n <div className=\"flex-1 overflow-y-auto\">\n <MessageList messages={messages} />\n </div>\n {error ? (\n <div className=\"border-t border-lt-danger/40 px-3 py-2 text-xs text-lt-danger\">{error}</div>\n ) : null}\n <PromptInput\n disabled={disabled}\n onSubmit={sendMessage}\n placeholder={props.placeholder ?? undefined}\n />\n </div>\n );\n};\n\nexport default ChatBox;\n"],"mappings":";;;;;;;;;;;AAeA,IAAa,WAA0C,EAAE,WAAW;CAClE,MAAM,QAAsB,KAAK;CACjC,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,YAAY,cACT,MAAM,SAAS,gCAAgC,MAAM,MAAM,IAAI,qBACtE,CAAC,MAAM,MAAM,CACf;CACA,MAAM,EAAE,UAAU,QAAQ,OAAO,aAAa,gBAAgB,QAAQ;EACpE,UAAU,MAAM,kBAAkB;EAClC;CACF,CAAC;CAED,MAAM,YAAY,OAAO,KAAK;CAE9B,MAAM,cAAc,YAAY,YAA2B;EACzD,IAAI,UAAU,WAAW,CAAC,MAAM,iBAC9B;EAGF,UAAU,UAAU;EAEpB,IAAI,MAAM,QAAQ;GAIhB,aAAY,MAHU,WAAgC,MAAM,iBAAiB,EAC3E,QAAQ,MAAM,OAChB,CAAC,GACmB,QAAQ;GAE5B;EACF;EAEA,MAAM,WAAW,MAAM,SAAS,MAAM,iBAAiB,EAAE,cAAc,MAAM,CAAC;EAE9E,IAAI,CAAC,SAAS,IACZ;EAIF,aAAY,MADW,SAAS,KAAK,GACjB,QAAQ;CAC9B,GAAG;EAAC,MAAM;EAAiB,MAAM;EAAQ;CAAW,CAAC;CAErD,gBAAgB;EACd,YAAiB,EAAE,YAAY,CAAC,CAAC;CACnC,GAAG,CAAC,WAAW,CAAC;CAGhB,MAAM,WADO,WAAW,eAAe,WAAW,eACzB,CAAC,MAAM;CAEhC,OACE,qBAAC,OAAD;EACE,WAAW,GACT,kEACA,MAAM,OACF,6CACA,wCACN;EACA,aAAW,aAAa,UAAU;YAPpC;GASE,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,QAAD;KAAM,WAAU;eACb,MAAM,SAAS,EAAE,qBAAqB,MAAM;IACzC,CAAA;GACH,CAAA;GACL,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,aAAD,EAAuB,SAAW,CAAA;GAC/B,CAAA;GACJ,QACC,oBAAC,OAAD;IAAK,WAAU;cAAiE;GAAW,CAAA,IACzF;GACJ,oBAAC,aAAD;IACY;IACV,UAAU;IACV,aAAa,MAAM,eAAe,KAAA;GACnC,CAAA;EACE;;AAET"}
@@ -23,7 +23,7 @@ function PromptInput({ onSubmit, disabled = false, placeholder }) {
23
23
  return /* @__PURE__ */ jsxs("div", {
24
24
  className: "flex items-end gap-2 border-t border-lt-border p-3",
25
25
  children: [/* @__PURE__ */ jsx("textarea", {
26
- "aria-label": t("chat.input-label", "Message input"),
26
+ "aria-label": t("common.chat.input-label", "Message input"),
27
27
  className: cn("min-h-[2.5rem] flex-1 resize-none rounded-lt-sm border border-lt-input bg-lt-bg px-3 py-2 text-sm text-lt-fg placeholder:text-lt-muted-fg focus:outline-none focus:ring-1 focus:ring-lt-ring disabled:opacity-50"),
28
28
  "data-test": testIdentity("chat-input"),
29
29
  disabled,
@@ -39,7 +39,7 @@ function PromptInput({ onSubmit, disabled = false, placeholder }) {
39
39
  size: "sm",
40
40
  type: "button",
41
41
  variant: "default",
42
- children: t("chat.send", "Send")
42
+ children: t("common.chat.send", "Send")
43
43
  })]
44
44
  });
45
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-input.js","names":[],"sources":["../../../resources/js/chat/components/prompt-input.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { Button } from \"@lattice-php/lattice/core/components/button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\n\ntype PromptInputProps = {\n onSubmit: (text: string) => void;\n disabled?: boolean;\n placeholder?: string;\n};\n\nexport function PromptInput({\n onSubmit,\n disabled = false,\n placeholder,\n}: PromptInputProps): ReactNode {\n const { t } = useT(\"lattice\");\n const [value, setValue] = useState(\"\");\n\n function submit(): void {\n const trimmed = value.trim();\n if (trimmed === \"\" || disabled) {\n return;\n }\n\n onSubmit(trimmed);\n setValue(\"\");\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLTextAreaElement>): void {\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n submit();\n }\n }\n\n return (\n <div className=\"flex items-end gap-2 border-t border-lt-border p-3\">\n <textarea\n aria-label={t(\"chat.input-label\", \"Message input\")}\n className={cn(\n \"min-h-[2.5rem] flex-1 resize-none rounded-lt-sm border border-lt-input bg-lt-bg px-3 py-2 text-sm text-lt-fg placeholder:text-lt-muted-fg focus:outline-none focus:ring-1 focus:ring-lt-ring disabled:opacity-50\",\n )}\n data-test={testIdentity(\"chat-input\")}\n disabled={disabled}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={1}\n value={value}\n />\n <Button\n data-test={testIdentity(\"chat-send\")}\n disabled={disabled}\n onClick={submit}\n size=\"sm\"\n type=\"button\"\n variant=\"default\"\n >\n {t(\"chat.send\", \"Send\")}\n </Button>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAaA,SAAgB,YAAY,EAC1B,UACA,WAAW,OACX,eAC8B;CAC9B,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CAErC,SAAS,SAAe;EACtB,MAAM,UAAU,MAAM,KAAK;EAC3B,IAAI,YAAY,MAAM,UACpB;EAGF,SAAS,OAAO;EAChB,SAAS,EAAE;CACb;CAEA,SAAS,cAAc,OAAiD;EACtE,IAAI,MAAM,QAAQ,WAAW,CAAC,MAAM,UAAU;GAC5C,MAAM,eAAe;GACrB,OAAO;EACT;CACF;CAEA,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,YAAD;GACE,cAAY,EAAE,oBAAoB,eAAe;GACjD,WAAW,GACT,kNACF;GACA,aAAW,aAAa,YAAY;GAC1B;GACV,WAAW,MAAM,SAAS,EAAE,OAAO,KAAK;GACxC,WAAW;GACE;GACb,MAAM;GACC;EACR,CAAA,GACD,oBAAC,QAAD;GACE,aAAW,aAAa,WAAW;GACzB;GACV,SAAS;GACT,MAAK;GACL,MAAK;GACL,SAAQ;aAEP,EAAE,aAAa,MAAM;EAChB,CAAA,CACL;;AAET"}
1
+ {"version":3,"file":"prompt-input.js","names":[],"sources":["../../../resources/js/chat/components/prompt-input.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { Button } from \"@lattice-php/lattice/core/components/button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\n\ntype PromptInputProps = {\n onSubmit: (text: string) => void;\n disabled?: boolean;\n placeholder?: string;\n};\n\nexport function PromptInput({\n onSubmit,\n disabled = false,\n placeholder,\n}: PromptInputProps): ReactNode {\n const { t } = useT(\"lattice\");\n const [value, setValue] = useState(\"\");\n\n function submit(): void {\n const trimmed = value.trim();\n if (trimmed === \"\" || disabled) {\n return;\n }\n\n onSubmit(trimmed);\n setValue(\"\");\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLTextAreaElement>): void {\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n submit();\n }\n }\n\n return (\n <div className=\"flex items-end gap-2 border-t border-lt-border p-3\">\n <textarea\n aria-label={t(\"common.chat.input-label\", \"Message input\")}\n className={cn(\n \"min-h-[2.5rem] flex-1 resize-none rounded-lt-sm border border-lt-input bg-lt-bg px-3 py-2 text-sm text-lt-fg placeholder:text-lt-muted-fg focus:outline-none focus:ring-1 focus:ring-lt-ring disabled:opacity-50\",\n )}\n data-test={testIdentity(\"chat-input\")}\n disabled={disabled}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={1}\n value={value}\n />\n <Button\n data-test={testIdentity(\"chat-send\")}\n disabled={disabled}\n onClick={submit}\n size=\"sm\"\n type=\"button\"\n variant=\"default\"\n >\n {t(\"common.chat.send\", \"Send\")}\n </Button>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAaA,SAAgB,YAAY,EAC1B,UACA,WAAW,OACX,eAC8B;CAC9B,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CAErC,SAAS,SAAe;EACtB,MAAM,UAAU,MAAM,KAAK;EAC3B,IAAI,YAAY,MAAM,UACpB;EAGF,SAAS,OAAO;EAChB,SAAS,EAAE;CACb;CAEA,SAAS,cAAc,OAAiD;EACtE,IAAI,MAAM,QAAQ,WAAW,CAAC,MAAM,UAAU;GAC5C,MAAM,eAAe;GACrB,OAAO;EACT;CACF;CAEA,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,YAAD;GACE,cAAY,EAAE,2BAA2B,eAAe;GACxD,WAAW,GACT,kNACF;GACA,aAAW,aAAa,YAAY;GAC1B;GACV,WAAW,MAAM,SAAS,EAAE,OAAO,KAAK;GACxC,WAAW;GACE;GACb,MAAM;GACC;EACR,CAAA,GACD,oBAAC,QAAD;GACE,aAAW,aAAa,WAAW;GACzB;GACV,SAAS;GACT,MAAK;GACL,MAAK;GACL,SAAQ;aAEP,EAAE,oBAAoB,MAAM;EACvB,CAAA,CACL;;AAET"}
@@ -53,7 +53,7 @@ function Combobox({ contentClassName, emptyLabel, loading = false, multiple = fa
53
53
  children: [showSearch && /* @__PURE__ */ jsxs("div", {
54
54
  className: "flex items-center gap-2 border-b border-lt-border px-3 py-2",
55
55
  children: [/* @__PURE__ */ jsx("input", {
56
- "aria-label": searchLabel ?? t("a11y.searchOptions", "Search options"),
56
+ "aria-label": searchLabel ?? t("form.searchOptions", "Search options"),
57
57
  "data-slot": "combobox-search",
58
58
  "data-test": testId ? `${testId}-search` : void 0,
59
59
  className: "w-full bg-transparent text-sm outline-none placeholder:text-lt-muted-fg",
@@ -1 +1 @@
1
- {"version":3,"file":"combobox.js","names":[],"sources":["../../../resources/js/core/components/combobox.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport * as React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { Option } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover\";\n\nconst SEARCH_DEBOUNCE_MS = 250;\n\n/**\n * A popover select list with an optional search box and single/multi selection.\n *\n * Selection state is controlled by the consumer (`selected` + `onSelect`); the\n * consumer also owns option fetching. Pass `onSearch` for remote search (the\n * combobox debounces the query and renders `options` as given); omit it to\n * filter the provided `options` locally by label. The combobox closes itself\n * after a single-select.\n */\nfunction Combobox({\n contentClassName,\n emptyLabel,\n loading = false,\n multiple = false,\n onSearch,\n onSelect,\n open,\n onOpenChange,\n options,\n searchLabel,\n searchPlaceholder,\n selected,\n showSearch = true,\n testId,\n trigger,\n triggerClassName,\n triggerProps,\n}: {\n contentClassName?: string;\n emptyLabel?: string;\n loading?: boolean;\n multiple?: boolean;\n onSearch?: (query: string) => void;\n onSelect: (value: string) => void;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n options: Option[];\n searchLabel?: string;\n searchPlaceholder?: string;\n selected: string[];\n showSearch?: boolean;\n testId?: string;\n trigger: React.ReactNode;\n triggerClassName?: string;\n triggerProps?: React.ComponentProps<\"button\"> & { \"data-test\"?: string };\n}) {\n const { t } = useT(\"lattice\");\n const [query, setQuery] = useState(\"\");\n\n useEffect(() => {\n if (!onSearch || !open) {\n return;\n }\n\n const timer = window.setTimeout(() => onSearch(query), SEARCH_DEBOUNCE_MS);\n\n return () => window.clearTimeout(timer);\n }, [query, onSearch, open]);\n\n const visibleOptions = onSearch\n ? options\n : options.filter((option) => option.label.toLowerCase().includes(query.toLowerCase()));\n\n function close(): void {\n setQuery(\"\");\n onOpenChange(false);\n }\n\n function choose(value: string): void {\n onSelect(value);\n\n if (!multiple) {\n close();\n }\n }\n\n return (\n <Popover open={open} onOpenChange={(next) => (next ? onOpenChange(true) : close())}>\n <PopoverTrigger asChild>\n <button type=\"button\" className={triggerClassName} {...triggerProps}>\n {trigger}\n </button>\n </PopoverTrigger>\n\n <PopoverContent\n align=\"start\"\n className={cn(\n \"w-[var(--radix-popover-trigger-width)] overflow-hidden p-0\",\n contentClassName,\n )}\n >\n {showSearch && (\n <div className=\"flex items-center gap-2 border-b border-lt-border px-3 py-2\">\n <input\n aria-label={searchLabel ?? t(\"a11y.searchOptions\", \"Search options\")}\n data-slot=\"combobox-search\"\n data-test={testId ? `${testId}-search` : undefined}\n className=\"w-full bg-transparent text-sm outline-none placeholder:text-lt-muted-fg\"\n onChange={(event) => setQuery(event.target.value)}\n placeholder={searchPlaceholder}\n value={query}\n />\n {loading && (\n <Icon\n name=\"loader-2\"\n aria-hidden=\"true\"\n className=\"size-lt-icon-md shrink-0 animate-spin text-lt-muted-fg\"\n />\n )}\n </div>\n )}\n\n <div className=\"max-h-60 overflow-y-auto p-1\" role=\"listbox\">\n {visibleOptions.length === 0 ? (\n <p className=\"px-3 py-2 text-sm text-lt-muted-fg\">{emptyLabel}</p>\n ) : (\n visibleOptions.map((option) => {\n const isSelected = selected.includes(option.value);\n\n return (\n <button\n aria-selected={isSelected}\n className={cn(\n \"flex w-full items-center justify-between gap-2 rounded-lt-sm px-3 py-1.5 text-left text-sm transition-colors hover:bg-lt-accent hover:text-lt-accent-fg\",\n isSelected && \"bg-lt-accent/60\",\n )}\n data-slot=\"combobox-option\"\n data-test={testId ? `${testId}-option-${option.value}` : undefined}\n data-value={option.value}\n key={option.value}\n onClick={() => choose(option.value)}\n role=\"option\"\n type=\"button\"\n >\n {option.label}\n {isSelected && (\n <Icon name=\"check\" aria-hidden=\"true\" className=\"size-lt-icon-md shrink-0\" />\n )}\n </button>\n );\n })\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\nexport { Combobox };\n"],"mappings":";;;;;;;AAQA,IAAM,qBAAqB;;;;;;;;;;AAW3B,SAAS,SAAS,EAChB,kBACA,YACA,UAAU,OACV,WAAW,OACX,UACA,UACA,MACA,cACA,SACA,aACA,mBACA,UACA,aAAa,MACb,QACA,SACA,kBACA,gBAmBC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CAErC,gBAAgB;EACd,IAAI,CAAC,YAAY,CAAC,MAChB;EAGF,MAAM,QAAQ,OAAO,iBAAiB,SAAS,KAAK,GAAG,kBAAkB;EAEzE,aAAa,OAAO,aAAa,KAAK;CACxC,GAAG;EAAC;EAAO;EAAU;CAAI,CAAC;CAE1B,MAAM,iBAAiB,WACnB,UACA,QAAQ,QAAQ,WAAW,OAAO,MAAM,YAAY,EAAE,SAAS,MAAM,YAAY,CAAC,CAAC;CAEvF,SAAS,QAAc;EACrB,SAAS,EAAE;EACX,aAAa,KAAK;CACpB;CAEA,SAAS,OAAO,OAAqB;EACnC,SAAS,KAAK;EAEd,IAAI,CAAC,UACH,MAAM;CAEV;CAEA,OACE,qBAAC,SAAD;EAAe;EAAM,eAAe,SAAU,OAAO,aAAa,IAAI,IAAI,MAAM;YAAhF,CACE,oBAAC,gBAAD;GAAgB,SAAA;aACd,oBAAC,UAAD;IAAQ,MAAK;IAAS,WAAW;IAAkB,GAAI;cACpD;GACK,CAAA;EACM,CAAA,GAEhB,qBAAC,gBAAD;GACE,OAAM;GACN,WAAW,GACT,8DACA,gBACF;aALF,CAOG,cACC,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,SAAD;KACE,cAAY,eAAe,EAAE,sBAAsB,gBAAgB;KACnE,aAAU;KACV,aAAW,SAAS,GAAG,OAAO,WAAW,KAAA;KACzC,WAAU;KACV,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;KAChD,aAAa;KACb,OAAO;IACR,CAAA,GACA,WACC,oBAAC,MAAD;KACE,MAAK;KACL,eAAY;KACZ,WAAU;IACX,CAAA,CAEA;OAGP,oBAAC,OAAD;IAAK,WAAU;IAA+B,MAAK;cAChD,eAAe,WAAW,IACzB,oBAAC,KAAD;KAAG,WAAU;eAAsC;IAAc,CAAA,IAEjE,eAAe,KAAK,WAAW;KAC7B,MAAM,aAAa,SAAS,SAAS,OAAO,KAAK;KAEjD,OACE,qBAAC,UAAD;MACE,iBAAe;MACf,WAAW,GACT,2JACA,cAAc,iBAChB;MACA,aAAU;MACV,aAAW,SAAS,GAAG,OAAO,UAAU,OAAO,UAAU,KAAA;MACzD,cAAY,OAAO;MAEnB,eAAe,OAAO,OAAO,KAAK;MAClC,MAAK;MACL,MAAK;gBAZP,CAcG,OAAO,OACP,cACC,oBAAC,MAAD;OAAM,MAAK;OAAQ,eAAY;OAAO,WAAU;MAA4B,CAAA,CAExE;QATD,OAAO,KASN;IAEZ,CAAC;GAEA,CAAA,CACS;IACT;;AAEb"}
1
+ {"version":3,"file":"combobox.js","names":[],"sources":["../../../resources/js/core/components/combobox.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport * as React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { Option } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover\";\n\nconst SEARCH_DEBOUNCE_MS = 250;\n\n/**\n * A popover select list with an optional search box and single/multi selection.\n *\n * Selection state is controlled by the consumer (`selected` + `onSelect`); the\n * consumer also owns option fetching. Pass `onSearch` for remote search (the\n * combobox debounces the query and renders `options` as given); omit it to\n * filter the provided `options` locally by label. The combobox closes itself\n * after a single-select.\n */\nfunction Combobox({\n contentClassName,\n emptyLabel,\n loading = false,\n multiple = false,\n onSearch,\n onSelect,\n open,\n onOpenChange,\n options,\n searchLabel,\n searchPlaceholder,\n selected,\n showSearch = true,\n testId,\n trigger,\n triggerClassName,\n triggerProps,\n}: {\n contentClassName?: string;\n emptyLabel?: string;\n loading?: boolean;\n multiple?: boolean;\n onSearch?: (query: string) => void;\n onSelect: (value: string) => void;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n options: Option[];\n searchLabel?: string;\n searchPlaceholder?: string;\n selected: string[];\n showSearch?: boolean;\n testId?: string;\n trigger: React.ReactNode;\n triggerClassName?: string;\n triggerProps?: React.ComponentProps<\"button\"> & { \"data-test\"?: string };\n}) {\n const { t } = useT(\"lattice\");\n const [query, setQuery] = useState(\"\");\n\n useEffect(() => {\n if (!onSearch || !open) {\n return;\n }\n\n const timer = window.setTimeout(() => onSearch(query), SEARCH_DEBOUNCE_MS);\n\n return () => window.clearTimeout(timer);\n }, [query, onSearch, open]);\n\n const visibleOptions = onSearch\n ? options\n : options.filter((option) => option.label.toLowerCase().includes(query.toLowerCase()));\n\n function close(): void {\n setQuery(\"\");\n onOpenChange(false);\n }\n\n function choose(value: string): void {\n onSelect(value);\n\n if (!multiple) {\n close();\n }\n }\n\n return (\n <Popover open={open} onOpenChange={(next) => (next ? onOpenChange(true) : close())}>\n <PopoverTrigger asChild>\n <button type=\"button\" className={triggerClassName} {...triggerProps}>\n {trigger}\n </button>\n </PopoverTrigger>\n\n <PopoverContent\n align=\"start\"\n className={cn(\n \"w-[var(--radix-popover-trigger-width)] overflow-hidden p-0\",\n contentClassName,\n )}\n >\n {showSearch && (\n <div className=\"flex items-center gap-2 border-b border-lt-border px-3 py-2\">\n <input\n aria-label={searchLabel ?? t(\"form.searchOptions\", \"Search options\")}\n data-slot=\"combobox-search\"\n data-test={testId ? `${testId}-search` : undefined}\n className=\"w-full bg-transparent text-sm outline-none placeholder:text-lt-muted-fg\"\n onChange={(event) => setQuery(event.target.value)}\n placeholder={searchPlaceholder}\n value={query}\n />\n {loading && (\n <Icon\n name=\"loader-2\"\n aria-hidden=\"true\"\n className=\"size-lt-icon-md shrink-0 animate-spin text-lt-muted-fg\"\n />\n )}\n </div>\n )}\n\n <div className=\"max-h-60 overflow-y-auto p-1\" role=\"listbox\">\n {visibleOptions.length === 0 ? (\n <p className=\"px-3 py-2 text-sm text-lt-muted-fg\">{emptyLabel}</p>\n ) : (\n visibleOptions.map((option) => {\n const isSelected = selected.includes(option.value);\n\n return (\n <button\n aria-selected={isSelected}\n className={cn(\n \"flex w-full items-center justify-between gap-2 rounded-lt-sm px-3 py-1.5 text-left text-sm transition-colors hover:bg-lt-accent hover:text-lt-accent-fg\",\n isSelected && \"bg-lt-accent/60\",\n )}\n data-slot=\"combobox-option\"\n data-test={testId ? `${testId}-option-${option.value}` : undefined}\n data-value={option.value}\n key={option.value}\n onClick={() => choose(option.value)}\n role=\"option\"\n type=\"button\"\n >\n {option.label}\n {isSelected && (\n <Icon name=\"check\" aria-hidden=\"true\" className=\"size-lt-icon-md shrink-0\" />\n )}\n </button>\n );\n })\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\nexport { Combobox };\n"],"mappings":";;;;;;;AAQA,IAAM,qBAAqB;;;;;;;;;;AAW3B,SAAS,SAAS,EAChB,kBACA,YACA,UAAU,OACV,WAAW,OACX,UACA,UACA,MACA,cACA,SACA,aACA,mBACA,UACA,aAAa,MACb,QACA,SACA,kBACA,gBAmBC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CAErC,gBAAgB;EACd,IAAI,CAAC,YAAY,CAAC,MAChB;EAGF,MAAM,QAAQ,OAAO,iBAAiB,SAAS,KAAK,GAAG,kBAAkB;EAEzE,aAAa,OAAO,aAAa,KAAK;CACxC,GAAG;EAAC;EAAO;EAAU;CAAI,CAAC;CAE1B,MAAM,iBAAiB,WACnB,UACA,QAAQ,QAAQ,WAAW,OAAO,MAAM,YAAY,EAAE,SAAS,MAAM,YAAY,CAAC,CAAC;CAEvF,SAAS,QAAc;EACrB,SAAS,EAAE;EACX,aAAa,KAAK;CACpB;CAEA,SAAS,OAAO,OAAqB;EACnC,SAAS,KAAK;EAEd,IAAI,CAAC,UACH,MAAM;CAEV;CAEA,OACE,qBAAC,SAAD;EAAe;EAAM,eAAe,SAAU,OAAO,aAAa,IAAI,IAAI,MAAM;YAAhF,CACE,oBAAC,gBAAD;GAAgB,SAAA;aACd,oBAAC,UAAD;IAAQ,MAAK;IAAS,WAAW;IAAkB,GAAI;cACpD;GACK,CAAA;EACM,CAAA,GAEhB,qBAAC,gBAAD;GACE,OAAM;GACN,WAAW,GACT,8DACA,gBACF;aALF,CAOG,cACC,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,SAAD;KACE,cAAY,eAAe,EAAE,sBAAsB,gBAAgB;KACnE,aAAU;KACV,aAAW,SAAS,GAAG,OAAO,WAAW,KAAA;KACzC,WAAU;KACV,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;KAChD,aAAa;KACb,OAAO;IACR,CAAA,GACA,WACC,oBAAC,MAAD;KACE,MAAK;KACL,eAAY;KACZ,WAAU;IACX,CAAA,CAEA;OAGP,oBAAC,OAAD;IAAK,WAAU;IAA+B,MAAK;cAChD,eAAe,WAAW,IACzB,oBAAC,KAAD;KAAG,WAAU;eAAsC;IAAc,CAAA,IAEjE,eAAe,KAAK,WAAW;KAC7B,MAAM,aAAa,SAAS,SAAS,OAAO,KAAK;KAEjD,OACE,qBAAC,UAAD;MACE,iBAAe;MACf,WAAW,GACT,2JACA,cAAc,iBAChB;MACA,aAAU;MACV,aAAW,SAAS,GAAG,OAAO,UAAU,OAAO,UAAU,KAAA;MACzD,cAAY,OAAO;MAEnB,eAAe,OAAO,OAAO,KAAK;MAClC,MAAK;MACL,MAAK;gBAZP,CAcG,OAAO,OACP,cACC,oBAAC,MAAD;OAAM,MAAK;OAAQ,eAAY;OAAO,WAAU;MAA4B,CAAA,CAExE;QATD,OAAO,KASN;IAEZ,CAAC;GAEA,CAAA,CACS;IACT;;AAEb"}
@@ -11,7 +11,10 @@ var fragmentSizeHeights = {
11
11
  md: 64,
12
12
  sm: 40,
13
13
  xl: 384,
14
- xs: 32
14
+ xs: 32,
15
+ "2xl": 448,
16
+ "3xl": 512,
17
+ "4xl": 576
15
18
  };
16
19
  var FragmentComponent = ({ node }) => {
17
20
  const endpoint = node.props.endpoint ?? "";
@@ -1 +1 @@
1
- {"version":3,"file":"fragment.js","names":[],"sources":["../../../resources/js/core/components/fragment.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport { apiJson } from \"@lattice-php/lattice/core/api\";\nimport { Skeleton } from \"@lattice-php/lattice/core/components/skeleton\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport type { RendererComponent, Schema } from \"@lattice-php/lattice/core/types\";\nimport { toNodes } from \"@lattice-php/lattice/core/nodes\";\nimport { LATTICE_EVENT, type ReloadComponentEvent } from \"@lattice-php/lattice/events/event-names\";\n\ntype FragmentResponse = {\n schema?: Schema;\n};\n\nconst fragmentSizeHeights = {\n lg: 320,\n md: 64,\n sm: 40,\n xl: 384,\n xs: 32,\n} as const;\n\nconst FragmentComponent: RendererComponent<\"fragment\"> = ({ node }) => {\n const endpoint = node.props.endpoint ?? \"\";\n const isLazy = node.props.lazy === true;\n const componentRef = node.props.ref ?? \"\";\n const placeholderHeight = fragmentSizeHeights[node.props.size];\n const [components, setComponents] = useState(() => node.schema ?? []);\n const [hasLoaded, setHasLoaded] = useState(!isLazy);\n const [processing, setProcessing] = useState(isLazy && endpoint !== \"\");\n\n const load = useCallback(async (): Promise<void> => {\n if (!endpoint) {\n return;\n }\n\n setProcessing(true);\n\n try {\n const result = await apiJson<FragmentResponse>(endpoint, { ref: componentRef });\n\n setComponents(toNodes(result.schema));\n setHasLoaded(true);\n } finally {\n setProcessing(false);\n }\n }, [endpoint, componentRef]);\n\n useEffect(() => {\n if (!isLazy || hasLoaded) {\n return;\n }\n\n void load();\n }, [hasLoaded, isLazy, load]);\n\n useEffect(() => {\n function reload(event: Event): void {\n const detail = (event as ReloadComponentEvent).detail;\n\n if (detail?.component !== node.id) {\n return;\n }\n\n void load();\n }\n\n window.addEventListener(LATTICE_EVENT.reloadComponent, reload);\n\n return () => window.removeEventListener(LATTICE_EVENT.reloadComponent, reload);\n }, [load, node.id]);\n\n useEffect(() => {\n function reloadOnLocaleChange(): void {\n if (!hasLoaded) {\n return;\n }\n\n void load();\n }\n\n window.addEventListener(LATTICE_EVENT.localeChange, reloadOnLocaleChange);\n\n return () => window.removeEventListener(LATTICE_EVENT.localeChange, reloadOnLocaleChange);\n }, [hasLoaded, load]);\n\n return (\n <div\n data-lattice-fragment={node.id}\n style={processing && components.length === 0 ? { minHeight: placeholderHeight } : undefined}\n >\n {processing && components.length === 0 ? (\n <Skeleton className=\"w-full\" style={{ height: placeholderHeight }} />\n ) : (\n <Renderer nodes={components} />\n )}\n </div>\n );\n};\n\nexport default FragmentComponent;\n"],"mappings":";;;;;;;;AAYA,IAAM,sBAAsB;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,qBAAoD,EAAE,WAAW;CACrE,MAAM,WAAW,KAAK,MAAM,YAAY;CACxC,MAAM,SAAS,KAAK,MAAM,SAAS;CACnC,MAAM,eAAe,KAAK,MAAM,OAAO;CACvC,MAAM,oBAAoB,oBAAoB,KAAK,MAAM;CACzD,MAAM,CAAC,YAAY,iBAAiB,eAAe,KAAK,UAAU,CAAC,CAAC;CACpE,MAAM,CAAC,WAAW,gBAAgB,SAAS,CAAC,MAAM;CAClD,MAAM,CAAC,YAAY,iBAAiB,SAAS,UAAU,aAAa,EAAE;CAEtE,MAAM,OAAO,YAAY,YAA2B;EAClD,IAAI,CAAC,UACH;EAGF,cAAc,IAAI;EAElB,IAAI;GAGF,cAAc,SAAQ,MAFD,QAA0B,UAAU,EAAE,KAAK,aAAa,CAAC,GAEjD,MAAM,CAAC;GACpC,aAAa,IAAI;EACnB,UAAU;GACR,cAAc,KAAK;EACrB;CACF,GAAG,CAAC,UAAU,YAAY,CAAC;CAE3B,gBAAgB;EACd,IAAI,CAAC,UAAU,WACb;EAGF,KAAU;CACZ,GAAG;EAAC;EAAW;EAAQ;CAAI,CAAC;CAE5B,gBAAgB;EACd,SAAS,OAAO,OAAoB;GAGlC,IAFgB,MAA+B,QAEnC,cAAc,KAAK,IAC7B;GAGF,KAAU;EACZ;EAEA,OAAO,iBAAiB,cAAc,iBAAiB,MAAM;EAE7D,aAAa,OAAO,oBAAoB,cAAc,iBAAiB,MAAM;CAC/E,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC;CAElB,gBAAgB;EACd,SAAS,uBAA6B;GACpC,IAAI,CAAC,WACH;GAGF,KAAU;EACZ;EAEA,OAAO,iBAAiB,cAAc,cAAc,oBAAoB;EAExE,aAAa,OAAO,oBAAoB,cAAc,cAAc,oBAAoB;CAC1F,GAAG,CAAC,WAAW,IAAI,CAAC;CAEpB,OACE,oBAAC,OAAD;EACE,yBAAuB,KAAK;EAC5B,OAAO,cAAc,WAAW,WAAW,IAAI,EAAE,WAAW,kBAAkB,IAAI,KAAA;YAEjF,cAAc,WAAW,WAAW,IACnC,oBAAC,UAAD;GAAU,WAAU;GAAS,OAAO,EAAE,QAAQ,kBAAkB;EAAI,CAAA,IAEpE,oBAAC,UAAD,EAAU,OAAO,WAAa,CAAA;CAE7B,CAAA;AAET"}
1
+ {"version":3,"file":"fragment.js","names":[],"sources":["../../../resources/js/core/components/fragment.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport { apiJson } from \"@lattice-php/lattice/core/api\";\nimport { Skeleton } from \"@lattice-php/lattice/core/components/skeleton\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport type { RendererComponent, Schema } from \"@lattice-php/lattice/core/types\";\nimport { toNodes } from \"@lattice-php/lattice/core/nodes\";\nimport { LATTICE_EVENT, type ReloadComponentEvent } from \"@lattice-php/lattice/events/event-names\";\n\ntype FragmentResponse = {\n schema?: Schema;\n};\n\nconst fragmentSizeHeights = {\n lg: 320,\n md: 64,\n sm: 40,\n xl: 384,\n xs: 32,\n \"2xl\": 448,\n \"3xl\": 512,\n \"4xl\": 576,\n} as const;\n\nconst FragmentComponent: RendererComponent<\"fragment\"> = ({ node }) => {\n const endpoint = node.props.endpoint ?? \"\";\n const isLazy = node.props.lazy === true;\n const componentRef = node.props.ref ?? \"\";\n const placeholderHeight = fragmentSizeHeights[node.props.size];\n const [components, setComponents] = useState(() => node.schema ?? []);\n const [hasLoaded, setHasLoaded] = useState(!isLazy);\n const [processing, setProcessing] = useState(isLazy && endpoint !== \"\");\n\n const load = useCallback(async (): Promise<void> => {\n if (!endpoint) {\n return;\n }\n\n setProcessing(true);\n\n try {\n const result = await apiJson<FragmentResponse>(endpoint, { ref: componentRef });\n\n setComponents(toNodes(result.schema));\n setHasLoaded(true);\n } finally {\n setProcessing(false);\n }\n }, [endpoint, componentRef]);\n\n useEffect(() => {\n if (!isLazy || hasLoaded) {\n return;\n }\n\n void load();\n }, [hasLoaded, isLazy, load]);\n\n useEffect(() => {\n function reload(event: Event): void {\n const detail = (event as ReloadComponentEvent).detail;\n\n if (detail?.component !== node.id) {\n return;\n }\n\n void load();\n }\n\n window.addEventListener(LATTICE_EVENT.reloadComponent, reload);\n\n return () => window.removeEventListener(LATTICE_EVENT.reloadComponent, reload);\n }, [load, node.id]);\n\n useEffect(() => {\n function reloadOnLocaleChange(): void {\n if (!hasLoaded) {\n return;\n }\n\n void load();\n }\n\n window.addEventListener(LATTICE_EVENT.localeChange, reloadOnLocaleChange);\n\n return () => window.removeEventListener(LATTICE_EVENT.localeChange, reloadOnLocaleChange);\n }, [hasLoaded, load]);\n\n return (\n <div\n data-lattice-fragment={node.id}\n style={processing && components.length === 0 ? { minHeight: placeholderHeight } : undefined}\n >\n {processing && components.length === 0 ? (\n <Skeleton className=\"w-full\" style={{ height: placeholderHeight }} />\n ) : (\n <Renderer nodes={components} />\n )}\n </div>\n );\n};\n\nexport default FragmentComponent;\n"],"mappings":";;;;;;;;AAYA,IAAM,sBAAsB;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,qBAAoD,EAAE,WAAW;CACrE,MAAM,WAAW,KAAK,MAAM,YAAY;CACxC,MAAM,SAAS,KAAK,MAAM,SAAS;CACnC,MAAM,eAAe,KAAK,MAAM,OAAO;CACvC,MAAM,oBAAoB,oBAAoB,KAAK,MAAM;CACzD,MAAM,CAAC,YAAY,iBAAiB,eAAe,KAAK,UAAU,CAAC,CAAC;CACpE,MAAM,CAAC,WAAW,gBAAgB,SAAS,CAAC,MAAM;CAClD,MAAM,CAAC,YAAY,iBAAiB,SAAS,UAAU,aAAa,EAAE;CAEtE,MAAM,OAAO,YAAY,YAA2B;EAClD,IAAI,CAAC,UACH;EAGF,cAAc,IAAI;EAElB,IAAI;GAGF,cAAc,SAAQ,MAFD,QAA0B,UAAU,EAAE,KAAK,aAAa,CAAC,GAEjD,MAAM,CAAC;GACpC,aAAa,IAAI;EACnB,UAAU;GACR,cAAc,KAAK;EACrB;CACF,GAAG,CAAC,UAAU,YAAY,CAAC;CAE3B,gBAAgB;EACd,IAAI,CAAC,UAAU,WACb;EAGF,KAAU;CACZ,GAAG;EAAC;EAAW;EAAQ;CAAI,CAAC;CAE5B,gBAAgB;EACd,SAAS,OAAO,OAAoB;GAGlC,IAFgB,MAA+B,QAEnC,cAAc,KAAK,IAC7B;GAGF,KAAU;EACZ;EAEA,OAAO,iBAAiB,cAAc,iBAAiB,MAAM;EAE7D,aAAa,OAAO,oBAAoB,cAAc,iBAAiB,MAAM;CAC/E,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC;CAElB,gBAAgB;EACd,SAAS,uBAA6B;GACpC,IAAI,CAAC,WACH;GAGF,KAAU;EACZ;EAEA,OAAO,iBAAiB,cAAc,cAAc,oBAAoB;EAExE,aAAa,OAAO,oBAAoB,cAAc,cAAc,oBAAoB;CAC1F,GAAG,CAAC,WAAW,IAAI,CAAC;CAEpB,OACE,oBAAC,OAAD;EACE,yBAAuB,KAAK;EAC5B,OAAO,cAAc,WAAW,WAAW,IAAI,EAAE,WAAW,kBAAkB,IAAI,KAAA;YAEjF,cAAc,WAAW,WAAW,IACnC,oBAAC,UAAD;GAAU,WAAU;GAAS,OAAO,EAAE,QAAQ,kBAAkB;EAAI,CAAA,IAEpE,oBAAC,UAAD,EAAU,OAAO,WAAa,CAAA;CAE7B,CAAA;AAET"}
@@ -7,7 +7,10 @@ var sizeClass = {
7
7
  sm: "size-lt-icon-sm",
8
8
  md: "size-lt-icon-md",
9
9
  lg: "size-lt-icon-lg",
10
- xl: "size-lt-icon-xl"
10
+ xl: "size-lt-icon-xl",
11
+ "2xl": "size-lt-icon-2xl",
12
+ "3xl": "size-lt-icon-3xl",
13
+ "4xl": "size-lt-icon-4xl"
11
14
  };
12
15
  var colorClass = {
13
16
  default: "text-lt-fg",
@@ -1 +1 @@
1
- {"version":3,"file":"icon.js","names":[],"sources":["../../../resources/js/core/components/icon.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Color, Size } from \"@lattice-php/lattice/types/generated\";\n\nconst sizeClass: Record<Size, string> = {\n xs: \"size-lt-icon-xs\",\n sm: \"size-lt-icon-sm\",\n md: \"size-lt-icon-md\",\n lg: \"size-lt-icon-lg\",\n xl: \"size-lt-icon-xl\",\n};\n\nconst colorClass: Record<Color, string> = {\n default: \"text-lt-fg\",\n muted: \"text-lt-muted-fg\",\n primary: \"text-lt-primary\",\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n danger: \"text-lt-danger\",\n};\n\nconst IconComponent: RendererComponent<\"icon\"> = ({ node }) => {\n const { name, size, color, class: className } = node.props;\n\n return (\n <IconRenderer\n icon={name}\n className={cn(sizeClass[size], color ? colorClass[color] : undefined, className)}\n />\n );\n};\n\nexport default IconComponent;\n"],"mappings":";;;;AAKA,IAAM,YAAkC;CACtC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,aAAoC;CACxC,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;AACV;AAEA,IAAM,iBAA4C,EAAE,WAAW;CAC7D,MAAM,EAAE,MAAM,MAAM,OAAO,OAAO,cAAc,KAAK;CAErD,OACE,oBAAC,cAAD;EACE,MAAM;EACN,WAAW,GAAG,UAAU,OAAO,QAAQ,WAAW,SAAS,KAAA,GAAW,SAAS;CAChF,CAAA;AAEL"}
1
+ {"version":3,"file":"icon.js","names":[],"sources":["../../../resources/js/core/components/icon.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Color, Size } from \"@lattice-php/lattice/types/generated\";\n\nconst sizeClass: Record<Size, string> = {\n xs: \"size-lt-icon-xs\",\n sm: \"size-lt-icon-sm\",\n md: \"size-lt-icon-md\",\n lg: \"size-lt-icon-lg\",\n xl: \"size-lt-icon-xl\",\n \"2xl\": \"size-lt-icon-2xl\",\n \"3xl\": \"size-lt-icon-3xl\",\n \"4xl\": \"size-lt-icon-4xl\",\n};\n\nconst colorClass: Record<Color, string> = {\n default: \"text-lt-fg\",\n muted: \"text-lt-muted-fg\",\n primary: \"text-lt-primary\",\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n danger: \"text-lt-danger\",\n};\n\nconst IconComponent: RendererComponent<\"icon\"> = ({ node }) => {\n const { name, size, color, class: className } = node.props;\n\n return (\n <IconRenderer\n icon={name}\n className={cn(sizeClass[size], color ? colorClass[color] : undefined, className)}\n />\n );\n};\n\nexport default IconComponent;\n"],"mappings":";;;;AAKA,IAAM,YAAkC;CACtC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,aAAoC;CACxC,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;AACV;AAEA,IAAM,iBAA4C,EAAE,WAAW;CAC7D,MAAM,EAAE,MAAM,MAAM,OAAO,OAAO,cAAc,KAAK;CAErD,OACE,oBAAC,cAAD;EACE,MAAM;EACN,WAAW,GAAG,UAAU,OAAO,QAAQ,WAAW,SAAS,KAAA,GAAW,SAAS;CAChF,CAAA;AAEL"}
@@ -8,7 +8,7 @@ function InfoTooltip({ content }) {
8
8
  if (!content) return null;
9
9
  return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
10
10
  type: "button",
11
- "aria-label": t("a11y.moreInfo", "More information"),
11
+ "aria-label": t("common.moreInfo", "More information"),
12
12
  className: "ml-1 inline-flex rounded-lt-sm text-lt-muted-fg outline-none hover:text-lt-fg focus-visible:text-lt-fg focus-visible:ring-lt-ring/50 focus-visible:ring-[3px]",
13
13
  children: /* @__PURE__ */ jsx(Icon, {
14
14
  name: "info",
@@ -1 +1 @@
1
- {"version":3,"file":"info-tooltip.js","names":[],"sources":["../../../resources/js/core/components/info-tooltip.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover\";\n\nexport function InfoTooltip({ content }: { content?: string | null }) {\n const { t } = useT(\"lattice\");\n\n if (!content) {\n return null;\n }\n\n return (\n <Popover>\n <PopoverTrigger\n type=\"button\"\n aria-label={t(\"a11y.moreInfo\", \"More information\")}\n className=\"ml-1 inline-flex rounded-lt-sm text-lt-muted-fg outline-none hover:text-lt-fg focus-visible:text-lt-fg focus-visible:ring-lt-ring/50 focus-visible:ring-[3px]\"\n >\n <Icon name=\"info\" className=\"size-lt-icon-sm\" />\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"max-w-xs p-3 text-sm [&_a]:underline\"\n dangerouslySetInnerHTML={{ __html: content }}\n />\n </Popover>\n );\n}\n"],"mappings":";;;;;AAIA,SAAgB,YAAY,EAAE,WAAwC;CACpE,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,IAAI,CAAC,SACH,OAAO;CAGT,OACE,qBAAC,SAAD,EAAA,UAAA,CACE,oBAAC,gBAAD;EACE,MAAK;EACL,cAAY,EAAE,iBAAiB,kBAAkB;EACjD,WAAU;YAEV,oBAAC,MAAD;GAAM,MAAK;GAAO,WAAU;EAAmB,CAAA;CACjC,CAAA,GAChB,oBAAC,gBAAD;EACE,OAAM;EACN,WAAU;EACV,yBAAyB,EAAE,QAAQ,QAAQ;CAC5C,CAAA,CACM,EAAA,CAAA;AAEb"}
1
+ {"version":3,"file":"info-tooltip.js","names":[],"sources":["../../../resources/js/core/components/info-tooltip.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover\";\n\nexport function InfoTooltip({ content }: { content?: string | null }) {\n const { t } = useT(\"lattice\");\n\n if (!content) {\n return null;\n }\n\n return (\n <Popover>\n <PopoverTrigger\n type=\"button\"\n aria-label={t(\"common.moreInfo\", \"More information\")}\n className=\"ml-1 inline-flex rounded-lt-sm text-lt-muted-fg outline-none hover:text-lt-fg focus-visible:text-lt-fg focus-visible:ring-lt-ring/50 focus-visible:ring-[3px]\"\n >\n <Icon name=\"info\" className=\"size-lt-icon-sm\" />\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"max-w-xs p-3 text-sm [&_a]:underline\"\n dangerouslySetInnerHTML={{ __html: content }}\n />\n </Popover>\n );\n}\n"],"mappings":";;;;;AAIA,SAAgB,YAAY,EAAE,WAAwC;CACpE,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,IAAI,CAAC,SACH,OAAO;CAGT,OACE,qBAAC,SAAD,EAAA,UAAA,CACE,oBAAC,gBAAD;EACE,MAAK;EACL,cAAY,EAAE,mBAAmB,kBAAkB;EACnD,WAAU;YAEV,oBAAC,MAAD;GAAM,MAAK;GAAO,WAAU;EAAmB,CAAA;CACjC,CAAA,GAChB,oBAAC,gBAAD;EACE,OAAM;EACN,WAAU;EACV,yBAAyB,EAAE,QAAQ,QAAQ;CAC5C,CAAA,CACM,EAAA,CAAA;AAEb"}
@@ -8,7 +8,7 @@ function Spinner({ className, ...props }) {
8
8
  return /* @__PURE__ */ jsx(Icon, {
9
9
  name: "loader-2",
10
10
  role: "status",
11
- "aria-label": t("a11y.loading", "Loading"),
11
+ "aria-label": t("common.loading", "Loading"),
12
12
  "aria-hidden": false,
13
13
  className: cn("animate-spin", className),
14
14
  ...props
@@ -1 +1 @@
1
- {"version":3,"file":"spinner.js","names":[],"sources":["../../../resources/js/core/components/spinner.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n const { t } = useT(\"lattice\");\n\n return (\n <Icon\n name=\"loader-2\"\n role=\"status\"\n aria-label={t(\"a11y.loading\", \"Loading\")}\n aria-hidden={false}\n className={cn(\"animate-spin\", className)}\n {...props}\n />\n );\n}\n\nexport { Spinner };\n"],"mappings":";;;;;AAIA,SAAS,QAAQ,EAAE,WAAW,GAAG,SAAsC;CACrE,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,oBAAC,MAAD;EACE,MAAK;EACL,MAAK;EACL,cAAY,EAAE,gBAAgB,SAAS;EACvC,eAAa;EACb,WAAW,GAAG,gBAAgB,SAAS;EACvC,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"spinner.js","names":[],"sources":["../../../resources/js/core/components/spinner.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n const { t } = useT(\"lattice\");\n\n return (\n <Icon\n name=\"loader-2\"\n role=\"status\"\n aria-label={t(\"common.loading\", \"Loading\")}\n aria-hidden={false}\n className={cn(\"animate-spin\", className)}\n {...props}\n />\n );\n}\n\nexport { Spinner };\n"],"mappings":";;;;;AAIA,SAAS,QAAQ,EAAE,WAAW,GAAG,SAAsC;CACrE,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,oBAAC,MAAD;EACE,MAAK;EACL,MAAK;EACL,cAAY,EAAE,kBAAkB,SAAS;EACzC,eAAa;EACb,WAAW,GAAG,gBAAgB,SAAS;EACvC,GAAI;CACL,CAAA;AAEL"}
@@ -92,7 +92,7 @@ var TabsComponent = ({ children, node }) => {
92
92
  className: cn("gap-6", isVertical ? cn("flex", alignment === "end" && "flex-row-reverse") : "grid"),
93
93
  "data-lattice-tabs": node.key ?? node.id,
94
94
  children: [/* @__PURE__ */ jsx("div", {
95
- "aria-label": t("a11y.tabs", "Tabs"),
95
+ "aria-label": t("common.tabs", "Tabs"),
96
96
  "aria-orientation": orientation,
97
97
  className: cn("gap-1 rounded-lt bg-lt-muted p-1", isVertical && "flex flex-col", isStretched && "flex w-full", !isVertical && !isStretched && cn("inline-flex w-fit max-w-full overflow-x-auto", {
98
98
  "justify-self-center": alignment === "center",
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","names":[],"sources":["../../../resources/js/core/components/tabs.tsx"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { Tab } from \"@lattice-php/lattice/types/generated\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\n\ntype TabsContextValue = {\n activeValue: string;\n setActiveValue: (value: string) => void;\n};\n\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\nfunction useTabsContext(): TabsContextValue {\n const context = useContext(TabsContext);\n\n if (!context) {\n return {\n activeValue: \"\",\n setActiveValue: () => {},\n };\n }\n\n return context;\n}\n\ntype TabItem = {\n confirm?: {\n required?: boolean;\n };\n label: string;\n value: string;\n};\n\nfunction getTabs(node: Node): TabItem[] {\n return (node.schema ?? [])\n .filter((child) => child.type === \"tab\")\n .map((child) => {\n const props = child.props as unknown as Tab;\n\n return {\n confirm: props.confirm ? { required: props.confirm.required } : undefined,\n label: props.label,\n value: props.value,\n };\n })\n .filter((tab) => tab.value !== \"\");\n}\n\nfunction queryValue(queryKey: string, tabs: Array<{ value: string }>): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n const value = new URLSearchParams(window.location.search).get(queryKey);\n\n if (!value || !tabs.some((tab) => tab.value === value)) {\n return null;\n }\n\n return value;\n}\n\nfunction replaceQueryValue(queryKey: string, value: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const url = new URL(window.location.href);\n url.searchParams.set(queryKey, value);\n window.history.replaceState(window.history.state, \"\", `${url.pathname}${url.search}${url.hash}`);\n}\n\nfunction queryUrl(queryKey: string, value: string): string {\n if (typeof window === \"undefined\") {\n return \"\";\n }\n\n const url = new URL(window.location.href);\n url.searchParams.set(queryKey, value);\n\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport const TabsComponent: RendererComponent<\"tabs\"> = ({ children, node }) => {\n const { t } = useT(\"lattice\");\n const tabs = useMemo(() => getTabs(node), [node]);\n const firstValue = tabs[0]?.value ?? \"\";\n const queryKey = node.props.queryKey;\n const orientation = node.props.orientation;\n const isVertical = orientation === \"vertical\";\n const alignment = node.props.alignment;\n const isStretched = !isVertical && alignment === \"stretch\";\n const serverActiveValue = node.props.activeValue;\n const defaultValue = node.props.defaultValue ?? firstValue;\n const tablistRef = useRef<HTMLDivElement>(null);\n const [activeValue, setActiveTabValue] = useState(\n () => serverActiveValue || (queryValue(queryKey, tabs) ?? defaultValue) || firstValue,\n );\n\n function selectTab(tab: TabItem): void {\n if (tab.confirm?.required) {\n router.visit(queryUrl(queryKey, tab.value), {\n preserveScroll: true,\n });\n\n return;\n }\n\n setActiveTabValue(tab.value);\n replaceQueryValue(queryKey, tab.value);\n }\n\n function selectTabValue(value: string): void {\n const tab = tabs.find((item) => item.value === value);\n\n if (tab) {\n selectTab(tab);\n }\n }\n\n function onTablistKeyDown(event: KeyboardEvent<HTMLButtonElement>): void {\n const nextKey = isVertical ? \"ArrowDown\" : \"ArrowRight\";\n const prevKey = isVertical ? \"ArrowUp\" : \"ArrowLeft\";\n\n if (\n event.key !== nextKey &&\n event.key !== prevKey &&\n event.key !== \"Home\" &&\n event.key !== \"End\"\n ) {\n return;\n }\n\n const buttons = Array.from(\n tablistRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]') ?? [],\n );\n\n if (buttons.length === 0) {\n return;\n }\n\n event.preventDefault();\n const current = buttons.indexOf(document.activeElement as HTMLButtonElement);\n\n let index: number;\n if (event.key === \"Home\") {\n index = 0;\n } else if (event.key === \"End\") {\n index = buttons.length - 1;\n } else {\n const delta = event.key === nextKey ? 1 : -1;\n const base = current < 0 ? 0 : current;\n index = (base + delta + buttons.length) % buttons.length;\n }\n\n buttons[index]?.focus();\n }\n\n return (\n <TabsContext.Provider value={{ activeValue, setActiveValue: selectTabValue }}>\n <div\n className={cn(\n \"gap-6\",\n isVertical ? cn(\"flex\", alignment === \"end\" && \"flex-row-reverse\") : \"grid\",\n )}\n data-lattice-tabs={node.key ?? node.id}\n >\n <div\n aria-label={t(\"a11y.tabs\", \"Tabs\")}\n aria-orientation={orientation}\n className={cn(\n \"gap-1 rounded-lt bg-lt-muted p-1\",\n isVertical && \"flex flex-col\",\n isStretched && \"flex w-full\",\n !isVertical &&\n !isStretched &&\n cn(\"inline-flex w-fit max-w-full overflow-x-auto\", {\n \"justify-self-center\": alignment === \"center\",\n \"justify-self-end\": alignment === \"end\",\n }),\n )}\n ref={tablistRef}\n role=\"tablist\"\n >\n {tabs.map((tab) => {\n const isActive = activeValue === tab.value;\n\n return (\n <button\n aria-controls={`${tab.value}-panel`}\n aria-selected={isActive}\n data-test={`tab-${tab.value}`}\n className={cn(\n \"whitespace-nowrap rounded-lt-sm px-3 py-1.5 text-sm font-medium transition-colors\",\n isActive\n ? \"bg-lt-bg text-lt-fg shadow-lt-xs\"\n : \"text-lt-muted-fg hover:bg-lt-bg/60 hover:text-lt-fg\",\n isVertical && \"text-left\",\n isStretched && \"flex-1\",\n )}\n id={`${tab.value}-tab`}\n key={tab.value}\n onClick={() => selectTab(tab)}\n onKeyDown={onTablistKeyDown}\n role=\"tab\"\n tabIndex={isActive ? 0 : -1}\n type=\"button\"\n >\n {tab.label}\n </button>\n );\n })}\n </div>\n\n <div className={cn(\"min-w-0\", isVertical && \"flex-1\")}>{children}</div>\n </div>\n </TabsContext.Provider>\n );\n};\n\nconst TabComponent: RendererComponent<\"tab\"> = ({ children, node }) => {\n const { activeValue } = useTabsContext();\n const value = node.props.value;\n const isActive = activeValue === value;\n const [hasOpened, setHasOpened] = useState(isActive);\n\n useEffect(() => {\n if (isActive) {\n setHasOpened(true);\n }\n }, [isActive]);\n\n return (\n <section\n aria-labelledby={`${value}-tab`}\n className={cn(\"space-y-8\", !isActive && \"hidden\")}\n hidden={!isActive}\n id={`${value}-panel`}\n role=\"tabpanel\"\n tabIndex={0}\n >\n {hasOpened ? (children as ReactNode) : null}\n </section>\n );\n};\n\nexport default TabComponent;\n"],"mappings":"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"}
1
+ {"version":3,"file":"tabs.js","names":[],"sources":["../../../resources/js/core/components/tabs.tsx"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { Tab } from \"@lattice-php/lattice/types/generated\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\n\ntype TabsContextValue = {\n activeValue: string;\n setActiveValue: (value: string) => void;\n};\n\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\nfunction useTabsContext(): TabsContextValue {\n const context = useContext(TabsContext);\n\n if (!context) {\n return {\n activeValue: \"\",\n setActiveValue: () => {},\n };\n }\n\n return context;\n}\n\ntype TabItem = {\n confirm?: {\n required?: boolean;\n };\n label: string;\n value: string;\n};\n\nfunction getTabs(node: Node): TabItem[] {\n return (node.schema ?? [])\n .filter((child) => child.type === \"tab\")\n .map((child) => {\n const props = child.props as unknown as Tab;\n\n return {\n confirm: props.confirm ? { required: props.confirm.required } : undefined,\n label: props.label,\n value: props.value,\n };\n })\n .filter((tab) => tab.value !== \"\");\n}\n\nfunction queryValue(queryKey: string, tabs: Array<{ value: string }>): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n const value = new URLSearchParams(window.location.search).get(queryKey);\n\n if (!value || !tabs.some((tab) => tab.value === value)) {\n return null;\n }\n\n return value;\n}\n\nfunction replaceQueryValue(queryKey: string, value: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const url = new URL(window.location.href);\n url.searchParams.set(queryKey, value);\n window.history.replaceState(window.history.state, \"\", `${url.pathname}${url.search}${url.hash}`);\n}\n\nfunction queryUrl(queryKey: string, value: string): string {\n if (typeof window === \"undefined\") {\n return \"\";\n }\n\n const url = new URL(window.location.href);\n url.searchParams.set(queryKey, value);\n\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport const TabsComponent: RendererComponent<\"tabs\"> = ({ children, node }) => {\n const { t } = useT(\"lattice\");\n const tabs = useMemo(() => getTabs(node), [node]);\n const firstValue = tabs[0]?.value ?? \"\";\n const queryKey = node.props.queryKey;\n const orientation = node.props.orientation;\n const isVertical = orientation === \"vertical\";\n const alignment = node.props.alignment;\n const isStretched = !isVertical && alignment === \"stretch\";\n const serverActiveValue = node.props.activeValue;\n const defaultValue = node.props.defaultValue ?? firstValue;\n const tablistRef = useRef<HTMLDivElement>(null);\n const [activeValue, setActiveTabValue] = useState(\n () => serverActiveValue || (queryValue(queryKey, tabs) ?? defaultValue) || firstValue,\n );\n\n function selectTab(tab: TabItem): void {\n if (tab.confirm?.required) {\n router.visit(queryUrl(queryKey, tab.value), {\n preserveScroll: true,\n });\n\n return;\n }\n\n setActiveTabValue(tab.value);\n replaceQueryValue(queryKey, tab.value);\n }\n\n function selectTabValue(value: string): void {\n const tab = tabs.find((item) => item.value === value);\n\n if (tab) {\n selectTab(tab);\n }\n }\n\n function onTablistKeyDown(event: KeyboardEvent<HTMLButtonElement>): void {\n const nextKey = isVertical ? \"ArrowDown\" : \"ArrowRight\";\n const prevKey = isVertical ? \"ArrowUp\" : \"ArrowLeft\";\n\n if (\n event.key !== nextKey &&\n event.key !== prevKey &&\n event.key !== \"Home\" &&\n event.key !== \"End\"\n ) {\n return;\n }\n\n const buttons = Array.from(\n tablistRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]') ?? [],\n );\n\n if (buttons.length === 0) {\n return;\n }\n\n event.preventDefault();\n const current = buttons.indexOf(document.activeElement as HTMLButtonElement);\n\n let index: number;\n if (event.key === \"Home\") {\n index = 0;\n } else if (event.key === \"End\") {\n index = buttons.length - 1;\n } else {\n const delta = event.key === nextKey ? 1 : -1;\n const base = current < 0 ? 0 : current;\n index = (base + delta + buttons.length) % buttons.length;\n }\n\n buttons[index]?.focus();\n }\n\n return (\n <TabsContext.Provider value={{ activeValue, setActiveValue: selectTabValue }}>\n <div\n className={cn(\n \"gap-6\",\n isVertical ? cn(\"flex\", alignment === \"end\" && \"flex-row-reverse\") : \"grid\",\n )}\n data-lattice-tabs={node.key ?? node.id}\n >\n <div\n aria-label={t(\"common.tabs\", \"Tabs\")}\n aria-orientation={orientation}\n className={cn(\n \"gap-1 rounded-lt bg-lt-muted p-1\",\n isVertical && \"flex flex-col\",\n isStretched && \"flex w-full\",\n !isVertical &&\n !isStretched &&\n cn(\"inline-flex w-fit max-w-full overflow-x-auto\", {\n \"justify-self-center\": alignment === \"center\",\n \"justify-self-end\": alignment === \"end\",\n }),\n )}\n ref={tablistRef}\n role=\"tablist\"\n >\n {tabs.map((tab) => {\n const isActive = activeValue === tab.value;\n\n return (\n <button\n aria-controls={`${tab.value}-panel`}\n aria-selected={isActive}\n data-test={`tab-${tab.value}`}\n className={cn(\n \"whitespace-nowrap rounded-lt-sm px-3 py-1.5 text-sm font-medium transition-colors\",\n isActive\n ? \"bg-lt-bg text-lt-fg shadow-lt-xs\"\n : \"text-lt-muted-fg hover:bg-lt-bg/60 hover:text-lt-fg\",\n isVertical && \"text-left\",\n isStretched && \"flex-1\",\n )}\n id={`${tab.value}-tab`}\n key={tab.value}\n onClick={() => selectTab(tab)}\n onKeyDown={onTablistKeyDown}\n role=\"tab\"\n tabIndex={isActive ? 0 : -1}\n type=\"button\"\n >\n {tab.label}\n </button>\n );\n })}\n </div>\n\n <div className={cn(\"min-w-0\", isVertical && \"flex-1\")}>{children}</div>\n </div>\n </TabsContext.Provider>\n );\n};\n\nconst TabComponent: RendererComponent<\"tab\"> = ({ children, node }) => {\n const { activeValue } = useTabsContext();\n const value = node.props.value;\n const isActive = activeValue === value;\n const [hasOpened, setHasOpened] = useState(isActive);\n\n useEffect(() => {\n if (isActive) {\n setHasOpened(true);\n }\n }, [isActive]);\n\n return (\n <section\n aria-labelledby={`${value}-tab`}\n className={cn(\"space-y-8\", !isActive && \"hidden\")}\n hidden={!isActive}\n id={`${value}-panel`}\n role=\"tabpanel\"\n tabIndex={0}\n >\n {hasOpened ? (children as ReactNode) : null}\n </section>\n );\n};\n\nexport default TabComponent;\n"],"mappings":"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"}
@@ -19,7 +19,10 @@ var textSizes = {
19
19
  sm: "text-sm leading-6",
20
20
  md: "text-base leading-7",
21
21
  lg: "text-lg leading-8",
22
- xl: "text-xl leading-8"
22
+ xl: "text-xl leading-8",
23
+ "2xl": "text-2xl leading-9",
24
+ "3xl": "text-3xl leading-10",
25
+ "4xl": "text-4xl leading-none"
23
26
  };
24
27
  var TextComponent = ({ node }) => {
25
28
  return /* @__PURE__ */ jsx("p", {
@@ -1 +1 @@
1
- {"version":3,"file":"text.js","names":[],"sources":["../../../resources/js/core/components/text.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Color, Size } from \"@lattice-php/lattice/types/generated\";\n\nconst textAlignments: Record<string, string> = {\n center: \"text-center\",\n left: \"text-left\",\n};\n\nconst textColors: Record<Color, string> = {\n default: \"text-lt-fg\",\n muted: \"text-lt-muted-fg\",\n primary: \"text-lt-primary\",\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n danger: \"text-lt-danger\",\n};\n\nconst textSizes: Record<Size, string> = {\n xs: \"text-xs leading-5\",\n sm: \"text-sm leading-6\",\n md: \"text-base leading-7\",\n lg: \"text-lg leading-8\",\n xl: \"text-xl leading-8\",\n};\n\nconst TextComponent: RendererComponent<\"text\"> = ({ node }) => {\n const align = node.props.align ?? \"left\";\n\n return (\n <p\n className={cn(\n \"m-0\",\n \"max-w-2xl\",\n textAlignments[align] ?? textAlignments.left,\n textColors[node.props.color],\n textSizes[node.props.size],\n )}\n >\n {node.props.text}\n </p>\n );\n};\n\nexport default TextComponent;\n"],"mappings":";;;AAIA,IAAM,iBAAyC;CAC7C,QAAQ;CACR,MAAM;AACR;AAEA,IAAM,aAAoC;CACxC,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;AACV;AAEA,IAAM,YAAkC;CACtC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,iBAA4C,EAAE,WAAW;CAG7D,OACE,oBAAC,KAAD;EACE,WAAW,GACT,OACA,aACA,eAPQ,KAAK,MAAM,SAAS,WAOH,eAAe,MACxC,WAAW,KAAK,MAAM,QACtB,UAAU,KAAK,MAAM,KACvB;YAEC,KAAK,MAAM;CACX,CAAA;AAEP"}
1
+ {"version":3,"file":"text.js","names":[],"sources":["../../../resources/js/core/components/text.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Color, Size } from \"@lattice-php/lattice/types/generated\";\n\nconst textAlignments: Record<string, string> = {\n center: \"text-center\",\n left: \"text-left\",\n};\n\nconst textColors: Record<Color, string> = {\n default: \"text-lt-fg\",\n muted: \"text-lt-muted-fg\",\n primary: \"text-lt-primary\",\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n danger: \"text-lt-danger\",\n};\n\nconst textSizes: Record<Size, string> = {\n xs: \"text-xs leading-5\",\n sm: \"text-sm leading-6\",\n md: \"text-base leading-7\",\n lg: \"text-lg leading-8\",\n xl: \"text-xl leading-8\",\n \"2xl\": \"text-2xl leading-9\",\n \"3xl\": \"text-3xl leading-10\",\n \"4xl\": \"text-4xl leading-none\",\n};\n\nconst TextComponent: RendererComponent<\"text\"> = ({ node }) => {\n const align = node.props.align ?? \"left\";\n\n return (\n <p\n className={cn(\n \"m-0\",\n \"max-w-2xl\",\n textAlignments[align] ?? textAlignments.left,\n textColors[node.props.color],\n textSizes[node.props.size],\n )}\n >\n {node.props.text}\n </p>\n );\n};\n\nexport default TextComponent;\n"],"mappings":";;;AAIA,IAAM,iBAAyC;CAC7C,QAAQ;CACR,MAAM;AACR;AAEA,IAAM,aAAoC;CACxC,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;AACV;AAEA,IAAM,YAAkC;CACtC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,iBAA4C,EAAE,WAAW;CAG7D,OACE,oBAAC,KAAD;EACE,WAAW,GACT,OACA,aACA,eAPQ,KAAK,MAAM,SAAS,WAOH,eAAe,MACxC,WAAW,KAAK,MAAM,QACtB,UAAU,KAAK,MAAM,KACvB;YAEC,KAAK,MAAM;CACX,CAAA;AAEP"}
@@ -1,4 +1,4 @@
1
- import { Input } from "../base/input.js";
1
+ import { LazyDatePickerControl } from "./lazy-date-picker-control.js";
2
2
  import { SimpleField } from "./simple-field.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region resources/js/form/components/fields/date-input.tsx
@@ -7,18 +7,19 @@ var DateInputComponent = ({ node }) => {
7
7
  return /* @__PURE__ */ jsx(SimpleField, {
8
8
  node,
9
9
  label: props.label ?? "",
10
- children: ({ name, testId, value, readOnly, disabled, commit }) => /* @__PURE__ */ jsx(Input, {
10
+ children: ({ name, testId, value, readOnly, disabled, change, blur }) => /* @__PURE__ */ jsx(LazyDatePickerControl, {
11
11
  autoFocus: props.autoFocus ?? false,
12
- "data-test": testId,
13
12
  disabled,
14
- id: name,
13
+ label: props.label ?? props.name,
15
14
  max: props.max || void 0,
16
15
  min: props.min || void 0,
16
+ mode: "date",
17
17
  name,
18
- onChange: (event) => commit(event.target.value),
18
+ onBlur: blur,
19
+ onChange: change,
19
20
  readOnly,
20
21
  tabIndex: props.tabIndex ?? void 0,
21
- type: "date",
22
+ testId: testId ?? props.name,
22
23
  value
23
24
  })
24
25
  });
@@ -1 +1 @@
1
- {"version":3,"file":"date-input.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-input.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { Input } from \"../base/input\";\nimport { SimpleField } from \"./simple-field\";\n\nexport const DateInputComponent: RendererComponent<\"field.date-input\"> = ({ node }) => {\n const props = node.props;\n\n return (\n <SimpleField node={node} label={props.label ?? \"\"}>\n {({ name, testId, value, readOnly, disabled, commit }) => (\n <Input\n autoFocus={props.autoFocus ?? false}\n data-test={testId}\n disabled={disabled}\n id={name}\n max={props.max || undefined}\n min={props.min || undefined}\n name={name}\n onChange={(event) => commit(event.target.value)}\n readOnly={readOnly}\n tabIndex={props.tabIndex ?? undefined}\n type=\"date\"\n value={value}\n />\n )}\n </SimpleField>\n );\n};\n"],"mappings":";;;;AAIA,IAAa,sBAA6D,EAAE,WAAW;CACrF,MAAM,QAAQ,KAAK;CAEnB,OACE,oBAAC,aAAD;EAAmB;EAAM,OAAO,MAAM,SAAS;aAC3C,EAAE,MAAM,QAAQ,OAAO,UAAU,UAAU,aAC3C,oBAAC,OAAD;GACE,WAAW,MAAM,aAAa;GAC9B,aAAW;GACD;GACV,IAAI;GACJ,KAAK,MAAM,OAAO,KAAA;GAClB,KAAK,MAAM,OAAO,KAAA;GACZ;GACN,WAAW,UAAU,OAAO,MAAM,OAAO,KAAK;GACpC;GACV,UAAU,MAAM,YAAY,KAAA;GAC5B,MAAK;GACE;EACR,CAAA;CAEQ,CAAA;AAEjB"}
1
+ {"version":3,"file":"date-input.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-input.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { LazyDatePickerControl } from \"./lazy-date-picker-control\";\nimport { SimpleField } from \"./simple-field\";\n\nexport const DateInputComponent: RendererComponent<\"field.date-input\"> = ({ node }) => {\n const props = node.props;\n\n return (\n <SimpleField node={node} label={props.label ?? \"\"}>\n {({ name, testId, value, readOnly, disabled, change, blur }) => (\n <LazyDatePickerControl\n autoFocus={props.autoFocus ?? false}\n disabled={disabled}\n label={props.label ?? props.name}\n max={props.max || undefined}\n min={props.min || undefined}\n mode=\"date\"\n name={name}\n onBlur={blur}\n onChange={change}\n readOnly={readOnly}\n tabIndex={props.tabIndex ?? undefined}\n testId={testId ?? props.name}\n value={value}\n />\n )}\n </SimpleField>\n );\n};\n"],"mappings":";;;;AAIA,IAAa,sBAA6D,EAAE,WAAW;CACrF,MAAM,QAAQ,KAAK;CAEnB,OACE,oBAAC,aAAD;EAAmB;EAAM,OAAO,MAAM,SAAS;aAC3C,EAAE,MAAM,QAAQ,OAAO,UAAU,UAAU,QAAQ,WACnD,oBAAC,uBAAD;GACE,WAAW,MAAM,aAAa;GACpB;GACV,OAAO,MAAM,SAAS,MAAM;GAC5B,KAAK,MAAM,OAAO,KAAA;GAClB,KAAK,MAAM,OAAO,KAAA;GAClB,MAAK;GACC;GACN,QAAQ;GACR,UAAU;GACA;GACV,UAAU,MAAM,YAAY,KAAA;GAC5B,QAAQ,UAAU,MAAM;GACjB;EACR,CAAA;CAEQ,CAAA;AAEjB"}
@@ -0,0 +1,18 @@
1
+ export type DatePickerControlProps = {
2
+ mode: "date" | "date-time";
3
+ label: string;
4
+ name: string;
5
+ testId: string;
6
+ value: unknown;
7
+ min?: string | null;
8
+ max?: string | null;
9
+ step?: number | null;
10
+ disabled: boolean;
11
+ readOnly: boolean;
12
+ autoFocus?: boolean;
13
+ tabIndex?: number | null;
14
+ timezone?: string;
15
+ onChange: (value: string) => void;
16
+ onBlur?: () => void;
17
+ };
18
+ export declare function DatePickerControl({ mode, label, name, testId, value, min, max, step, disabled, readOnly, autoFocus, tabIndex, timezone, onChange, onBlur, }: DatePickerControlProps): import("react").JSX.Element;