@lattice-php/lattice 0.19.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.
- package/dist/core/index.js +2 -2
- package/dist/core/types.d.ts +16 -4
- package/dist/create-app.d.ts +31 -3
- package/dist/create-app.js +48 -10
- package/dist/create-app.js.map +1 -1
- package/dist/effects/registry.d.ts +3 -3
- package/dist/effects/registry.js +4 -4
- package/dist/effects/registry.js.map +1 -1
- package/dist/form/components/base/field.d.ts +2 -2
- package/dist/form/components/base/field.js +2 -2
- package/dist/form/components/base/field.js.map +1 -1
- package/dist/form/components/fields/color-picker-field.d.ts +2 -0
- package/dist/form/components/fields/color-picker-field.js +57 -0
- package/dist/form/components/fields/color-picker-field.js.map +1 -0
- package/dist/form/components/fields/date-input.js +1 -1
- package/dist/form/components/fields/date-picker-field.js +1 -1
- package/dist/form/components/fields/date-time-input.js +1 -1
- package/dist/form/components/fields/file-upload.js +7 -12
- package/dist/form/components/fields/file-upload.js.map +1 -1
- package/dist/form/components/fields/number-input.js +1 -1
- package/dist/form/components/fields/rich-editor-field.js +35 -276
- package/dist/form/components/fields/rich-editor-field.js.map +1 -1
- package/dist/form/components/fields/row-action-menu.js +2 -2
- package/dist/form/components/fields/row-action-menu.js.map +1 -1
- package/dist/form/components/fields/row-actions.js +3 -1
- package/dist/form/components/fields/row-actions.js.map +1 -1
- package/dist/form/components/fields/select.js +59 -16
- package/dist/form/components/fields/select.js.map +1 -1
- package/dist/form/components/fields/table-rows.js +2 -2
- package/dist/form/components/fields/table-rows.js.map +1 -1
- package/dist/form/components/fields/text-input.js +8 -1
- package/dist/form/components/fields/text-input.js.map +1 -1
- package/dist/form/components/fields/time-input.js +1 -1
- package/dist/form/components/index.d.ts +1 -0
- package/dist/form/components/index.js +2 -1
- package/dist/form/embed.d.ts +1 -0
- package/dist/form/embed.js +2 -1
- package/dist/form/hooks/use-form-resolver.js.map +1 -1
- package/dist/form/index.js +2 -1
- package/dist/form/lib/conditions.d.ts +4 -10
- package/dist/form/lib/conditions.js.map +1 -1
- package/dist/form/lib/field-props.d.ts +4 -18
- package/dist/form/lib/field-props.js.map +1 -1
- package/dist/form/plugin.js +2 -0
- package/dist/form/plugin.js.map +1 -1
- package/dist/form/rich-editor/builtins.d.ts +6 -0
- package/dist/form/rich-editor/builtins.js +400 -0
- package/dist/form/rich-editor/builtins.js.map +1 -0
- package/dist/form/rich-editor/index.d.ts +7 -0
- package/dist/form/rich-editor/index.js +3 -0
- package/dist/form/rich-editor/registry.d.ts +67 -0
- package/dist/form/rich-editor/registry.js +79 -0
- package/dist/form/rich-editor/registry.js.map +1 -0
- package/dist/form/rich-editor/toolbar-button.d.ts +12 -0
- package/dist/form/rich-editor/toolbar-button.js +28 -0
- package/dist/form/rich-editor/toolbar-button.js.map +1 -0
- package/dist/form/types.d.ts +1 -6
- package/dist/format/date-time.d.ts +3 -2
- package/dist/format/date-time.js.map +1 -1
- package/dist/i18n/backend.js +1 -1
- package/dist/i18n/date-time.d.ts +3 -2
- package/dist/i18n/date-time.js.map +1 -1
- package/dist/i18n/index.js +3 -2
- package/dist/i18n/instance.js +1 -1
- package/dist/i18n/page-props.d.ts +3 -2
- package/dist/i18n/page-props.js +1 -15
- package/dist/i18n/page-props.js.map +1 -1
- package/dist/i18n/shared-props.d.ts +7 -0
- package/dist/i18n/shared-props.js +25 -0
- package/dist/i18n/shared-props.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +7 -6
- package/dist/lattice.css +107 -47
- package/dist/layout/components/breadcrumbs.js +3 -1
- package/dist/layout/components/breadcrumbs.js.map +1 -1
- package/dist/layout/components/callouts.js +1 -1
- package/dist/lib/color.d.ts +9 -0
- package/dist/lib/color.js +48 -0
- package/dist/lib/color.js.map +1 -0
- package/dist/notifications/api.d.ts +6 -6
- package/dist/notifications/api.js.map +1 -1
- package/dist/notifications/types.d.ts +2 -10
- package/dist/provider-base.js +1 -1
- package/dist/realtime/build-effects.js +5 -5
- package/dist/realtime/build-effects.js.map +1 -1
- package/dist/realtime/listeners.d.ts +2 -2
- package/dist/realtime/listeners.js.map +1 -1
- package/dist/realtime/subscriptions.d.ts +2 -2
- package/dist/realtime/subscriptions.js.map +1 -1
- package/dist/table/components/bulk-bar.js +5 -5
- package/dist/table/components/bulk-bar.js.map +1 -1
- package/dist/table/components/cells/badge-cell.js +4 -1
- package/dist/table/components/cells/badge-cell.js.map +1 -1
- package/dist/table/components/cells/boolean-cell.js +3 -1
- package/dist/table/components/cells/boolean-cell.js.map +1 -1
- package/dist/table/components/cells/icon-cell.js +5 -2
- package/dist/table/components/cells/icon-cell.js.map +1 -1
- package/dist/table/components/cells/image-cell.js +8 -9
- package/dist/table/components/cells/image-cell.js.map +1 -1
- package/dist/table/components/cells/money-cell.js +9 -1
- package/dist/table/components/cells/money-cell.js.map +1 -1
- package/dist/table/components/cells/number-cell.js +9 -1
- package/dist/table/components/cells/number-cell.js.map +1 -1
- package/dist/table/components/cells/text-cell.js +4 -1
- package/dist/table/components/cells/text-cell.js.map +1 -1
- package/dist/table/components/column-filter-control.js +25 -32
- package/dist/table/components/column-filter-control.js.map +1 -1
- package/dist/table/components/column-header.d.ts +3 -3
- package/dist/table/components/column-header.js +5 -3
- package/dist/table/components/column-header.js.map +1 -1
- package/dist/table/components/column-visibility-menu.js +6 -11
- package/dist/table/components/column-visibility-menu.js.map +1 -1
- package/dist/table/components/filter-bar.d.ts +2 -2
- package/dist/table/components/filter-bar.js +13 -22
- package/dist/table/components/filter-bar.js.map +1 -1
- package/dist/table/components/filter-controls.d.ts +2 -1
- package/dist/table/components/filter-controls.js +36 -35
- package/dist/table/components/filter-controls.js.map +1 -1
- package/dist/table/components/filter-value-input.d.ts +0 -1
- package/dist/table/components/filter-value-input.js +21 -20
- package/dist/table/components/filter-value-input.js.map +1 -1
- package/dist/table/components/pagination.js +16 -20
- package/dist/table/components/pagination.js.map +1 -1
- package/dist/table/components/sort-bar.d.ts +3 -3
- package/dist/table/components/sort-bar.js +11 -12
- package/dist/table/components/sort-bar.js.map +1 -1
- package/dist/table/components/table-search.d.ts +9 -0
- package/dist/table/components/table-search.js +75 -0
- package/dist/table/components/table-search.js.map +1 -0
- package/dist/table/components/table.js +72 -19
- package/dist/table/components/table.js.map +1 -1
- package/dist/table/hooks/use-expanded-rows.d.ts +8 -0
- package/dist/table/hooks/use-expanded-rows.js +24 -0
- package/dist/table/hooks/use-expanded-rows.js.map +1 -0
- package/dist/table/hooks/use-table.d.ts +5 -3
- package/dist/table/hooks/use-table.js +56 -44
- package/dist/table/hooks/use-table.js.map +1 -1
- package/dist/table/lib/payload.d.ts +3 -2
- package/dist/table/lib/payload.js +16 -10
- package/dist/table/lib/payload.js.map +1 -1
- package/dist/table/lib/query.d.ts +5 -5
- package/dist/table/lib/query.js +20 -18
- package/dist/table/lib/query.js.map +1 -1
- package/dist/table/types.d.ts +3 -26
- package/dist/toast/callout.js +1 -3
- package/dist/toast/callout.js.map +1 -1
- package/dist/toast/toast.d.ts +1 -5
- package/dist/toast/toast.js +2 -7
- package/dist/toast/toast.js.map +1 -1
- package/dist/toast/toaster.js +2 -2
- package/dist/toast/toaster.js.map +1 -1
- package/dist/types/generated.d.ts +263 -188
- package/dist/ui/affix-group.d.ts +2 -1
- package/dist/ui/affix-group.js +9 -7
- package/dist/ui/affix-group.js.map +1 -1
- package/dist/ui/avatar.d.ts +3 -0
- package/dist/ui/avatar.js +52 -0
- package/dist/ui/avatar.js.map +1 -0
- package/dist/ui/button.d.ts +3 -1
- package/dist/ui/button.js +10 -3
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/chart-view.js +161 -11
- package/dist/ui/chart-view.js.map +1 -1
- package/dist/ui/click-behavior.d.ts +1 -1
- package/dist/ui/click-behavior.js.map +1 -1
- package/dist/ui/color-picker.d.ts +8 -0
- package/dist/ui/color-picker.js +59 -0
- package/dist/ui/color-picker.js.map +1 -0
- package/dist/ui/combobox.d.ts +11 -2
- package/dist/ui/combobox.js +51 -8
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/copyable-text.d.ts +7 -0
- package/dist/ui/copyable-text.js +21 -13
- package/dist/ui/copyable-text.js.map +1 -1
- package/dist/ui/fragment.js.map +1 -1
- package/dist/ui/heading.js +39 -21
- package/dist/ui/heading.js.map +1 -1
- package/dist/ui/icon-button.d.ts +22 -0
- package/dist/ui/icon-button.js +51 -0
- package/dist/ui/icon-button.js.map +1 -0
- package/dist/ui/icon.js +10 -11
- package/dist/ui/icon.js.map +1 -1
- package/dist/ui/image-preview.d.ts +12 -0
- package/dist/ui/image-preview.js +65 -0
- package/dist/ui/image-preview.js.map +1 -0
- package/dist/ui/image.d.ts +3 -0
- package/dist/ui/image.js +21 -0
- package/dist/ui/image.js.map +1 -0
- package/dist/ui/index.d.ts +2 -1
- package/dist/ui/index.js +4 -3
- package/dist/ui/info-tooltip.js +1 -1
- package/dist/ui/info-tooltip.js.map +1 -1
- package/dist/ui/input.d.ts +3 -1
- package/dist/ui/input.js +2 -2
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/modal.js +14 -2
- package/dist/ui/modal.js.map +1 -1
- package/dist/ui/native-select.d.ts +10 -0
- package/dist/ui/native-select.js +23 -0
- package/dist/ui/native-select.js.map +1 -0
- package/dist/ui/plugin.js +11 -1
- package/dist/ui/plugin.js.map +1 -1
- package/dist/ui/progress.d.ts +3 -0
- package/dist/ui/progress.js +114 -0
- package/dist/ui/progress.js.map +1 -0
- package/dist/ui/separator.d.ts +3 -0
- package/dist/ui/separator.js +15 -0
- package/dist/ui/separator.js.map +1 -0
- package/dist/ui/text.js +5 -10
- package/dist/ui/text.js.map +1 -1
- package/dist/ui/tree-context.d.ts +33 -0
- package/dist/ui/tree-context.js +137 -0
- package/dist/ui/tree-context.js.map +1 -0
- package/dist/ui/tree.d.ts +19 -0
- package/dist/ui/tree.js +187 -0
- package/dist/ui/tree.js.map +1 -0
- package/dist-standalone/chunks/chart-view-wJmnVu7L.js +36 -0
- package/dist-standalone/chunks/date-picker-field-VbH9xrQO.js +1 -0
- package/dist-standalone/chunks/jsx-runtime-Drll_-DD.js +1 -0
- package/dist-standalone/chunks/locale-CXqr7LPR.js +1 -0
- package/dist-standalone/chunks/page-props-AIa5UR6n.js +1 -0
- package/dist-standalone/chunks/rich-editor-field-DLQTyt36.js +154 -0
- package/dist-standalone/chunks/{subscriptions-B3UuDBmx.js → subscriptions-DY2tj9Im.js} +1 -1
- package/dist-standalone/chunks/use-effect-dispatcher-feEs0GCP.js +97 -0
- package/dist-standalone/lattice.css +1 -1
- package/dist-standalone/lattice.js +15 -15
- package/dist-standalone/manifest.json +11 -9
- package/dist-standalone/sprite.svg +1 -1
- package/package.json +6 -1
- package/resources/icons/code-xml.svg +17 -0
- package/resources/icons/heading.svg +17 -0
- package/dist-standalone/chunks/chart-view-CK5fKIkR.js +0 -36
- package/dist-standalone/chunks/date-picker-field-BlCPFhZd.js +0 -1
- package/dist-standalone/chunks/jsx-runtime-CJ_btYLc.js +0 -1
- package/dist-standalone/chunks/rich-editor-field-DH5dS5c1.js +0 -154
- package/dist-standalone/chunks/use-effect-dispatcher-k98Nzf9M.js +0 -97
package/dist/ui/affix-group.d.ts
CHANGED
|
@@ -10,8 +10,9 @@ import { Affix } from '../types/generated.js';
|
|
|
10
10
|
* affix segments. The control itself stays the focus target; only its own ring
|
|
11
11
|
* is suppressed.
|
|
12
12
|
*/
|
|
13
|
-
export declare function AffixGroup({ prefix, suffix, children, }: {
|
|
13
|
+
export declare function AffixGroup({ prefix, suffix, end, children, }: {
|
|
14
14
|
prefix?: Affix | null;
|
|
15
15
|
suffix?: Affix | null;
|
|
16
|
+
end?: ReactNode;
|
|
16
17
|
children: (controlClassName: string) => ReactNode;
|
|
17
18
|
}): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
|
package/dist/ui/affix-group.js
CHANGED
|
@@ -2,10 +2,10 @@ import { cn } from "../lib/utils.js";
|
|
|
2
2
|
import { IconRenderer } from "../icons/icon-renderer.js";
|
|
3
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
//#region resources/js/ui/affix-group.tsx
|
|
5
|
-
function AffixSegment({ affix, side }) {
|
|
5
|
+
function AffixSegment({ affix, side, squared = false }) {
|
|
6
6
|
return /* @__PURE__ */ jsx("span", {
|
|
7
7
|
"data-slot": `affix-${side}`,
|
|
8
|
-
className: cn("inline-flex h-lt-control-md shrink-0 items-center border border-lt-input bg-lt-muted px-3 text-base whitespace-nowrap text-lt-muted-fg", "group-has-[:focus-visible]:border-lt-ring", side === "start" ? "rounded-l-lt-sm border-r-0" : "rounded-r-lt-sm border-l-0"),
|
|
8
|
+
className: cn("inline-flex h-lt-control-md shrink-0 items-center border border-lt-input bg-lt-muted px-3 text-base whitespace-nowrap text-lt-muted-fg", "group-has-[:focus-visible]:border-lt-ring", side === "start" ? "rounded-l-lt-sm border-r-0" : "rounded-r-lt-sm border-l-0", squared && "rounded-r-none border-r-0"),
|
|
9
9
|
children: affix.icon ? /* @__PURE__ */ jsx(IconRenderer, {
|
|
10
10
|
className: "size-lt-icon-md",
|
|
11
11
|
icon: affix.icon
|
|
@@ -22,8 +22,8 @@ function AffixSegment({ affix, side }) {
|
|
|
22
22
|
* affix segments. The control itself stays the focus target; only its own ring
|
|
23
23
|
* is suppressed.
|
|
24
24
|
*/
|
|
25
|
-
function AffixGroup({ prefix, suffix, children }) {
|
|
26
|
-
if (!prefix && !suffix) return children("");
|
|
25
|
+
function AffixGroup({ prefix, suffix, end, children }) {
|
|
26
|
+
if (!prefix && !suffix && !end) return children("");
|
|
27
27
|
return /* @__PURE__ */ jsxs("div", {
|
|
28
28
|
className: "group flex w-full rounded-lt-sm transition-[color,box-shadow] has-[:focus-visible]:ring-[3px] has-[:focus-visible]:ring-lt-ring/50",
|
|
29
29
|
"data-slot": "affix-group",
|
|
@@ -34,12 +34,14 @@ function AffixGroup({ prefix, suffix, children }) {
|
|
|
34
34
|
}) : null,
|
|
35
35
|
/* @__PURE__ */ jsx("div", {
|
|
36
36
|
className: "min-w-0 flex-1",
|
|
37
|
-
children: children(cn("focus-visible:ring-0", prefix && "rounded-l-none", suffix && "rounded-r-none"))
|
|
37
|
+
children: children(cn("focus-visible:ring-0", prefix && "rounded-l-none", (suffix || end) && "rounded-r-none"))
|
|
38
38
|
}),
|
|
39
39
|
suffix ? /* @__PURE__ */ jsx(AffixSegment, {
|
|
40
40
|
affix: suffix,
|
|
41
|
-
side: "end"
|
|
42
|
-
|
|
41
|
+
side: "end",
|
|
42
|
+
squared: Boolean(end)
|
|
43
|
+
}) : null,
|
|
44
|
+
end
|
|
43
45
|
]
|
|
44
46
|
});
|
|
45
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"affix-group.js","names":[],"sources":["../../resources/js/ui/affix-group.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { Affix } from \"@lattice-php/lattice/types/generated\";\nimport { IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\n\nfunction AffixSegment({
|
|
1
|
+
{"version":3,"file":"affix-group.js","names":[],"sources":["../../resources/js/ui/affix-group.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { Affix } from \"@lattice-php/lattice/types/generated\";\nimport { IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\n\nfunction AffixSegment({\n affix,\n side,\n squared = false,\n}: {\n affix: Affix;\n side: \"start\" | \"end\";\n squared?: boolean;\n}) {\n return (\n <span\n data-slot={`affix-${side}`}\n className={cn(\n \"inline-flex h-lt-control-md shrink-0 items-center border border-lt-input bg-lt-muted px-3 text-base whitespace-nowrap text-lt-muted-fg\",\n \"group-has-[:focus-visible]:border-lt-ring\",\n side === \"start\" ? \"rounded-l-lt-sm border-r-0\" : \"rounded-r-lt-sm border-l-0\",\n squared && \"rounded-r-none border-r-0\",\n )}\n >\n {affix.icon ? <IconRenderer className=\"size-lt-icon-md\" icon={affix.icon} /> : affix.text}\n </span>\n );\n}\n\n/**\n * Wraps a single-line control in a prefix/suffix input group. The control is a\n * render prop receiving the class names that square the corners adjacent to an\n * affix; with no affixes the control renders untouched.\n *\n * The focus ring lives on the group, not the bare input, so it surrounds the\n * whole control — affixes included — instead of being clipped by the opaque\n * affix segments. The control itself stays the focus target; only its own ring\n * is suppressed.\n */\nexport function AffixGroup({\n prefix,\n suffix,\n end,\n children,\n}: {\n prefix?: Affix | null;\n suffix?: Affix | null;\n end?: ReactNode;\n children: (controlClassName: string) => ReactNode;\n}) {\n if (!prefix && !suffix && !end) {\n return children(\"\");\n }\n\n return (\n <div\n className=\"group flex w-full rounded-lt-sm transition-[color,box-shadow] has-[:focus-visible]:ring-[3px] has-[:focus-visible]:ring-lt-ring/50\"\n data-slot=\"affix-group\"\n >\n {prefix ? <AffixSegment affix={prefix} side=\"start\" /> : null}\n <div className=\"min-w-0 flex-1\">\n {children(\n cn(\n \"focus-visible:ring-0\",\n prefix && \"rounded-l-none\",\n (suffix || end) && \"rounded-r-none\",\n ),\n )}\n </div>\n {suffix ? <AffixSegment affix={suffix} side=\"end\" squared={Boolean(end)} /> : null}\n {end}\n </div>\n );\n}\n"],"mappings":";;;;AAKA,SAAS,aAAa,EACpB,OACA,MACA,UAAU,SAKT;CACD,OACE,oBAAC,QAAD;EACE,aAAW,SAAS;EACpB,WAAW,GACT,0IACA,6CACA,SAAS,UAAU,+BAA+B,8BAClD,WAAW,2BACb;YAEC,MAAM,OAAO,oBAAC,cAAD;GAAc,WAAU;GAAkB,MAAM,MAAM;EAAO,CAAA,IAAI,MAAM;CACjF,CAAA;AAEV;;;;;;;;;;;AAYA,SAAgB,WAAW,EACzB,QACA,QACA,KACA,YAMC;CACD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KACzB,OAAO,SAAS,EAAE;CAGpB,OACE,qBAAC,OAAD;EACE,WAAU;EACV,aAAU;YAFZ;GAIG,SAAS,oBAAC,cAAD;IAAc,OAAO;IAAQ,MAAK;GAAS,CAAA,IAAI;GACzD,oBAAC,OAAD;IAAK,WAAU;cACZ,SACC,GACE,wBACA,UAAU,mBACT,UAAU,QAAQ,gBACrB,CACF;GACG,CAAA;GACJ,SAAS,oBAAC,cAAD;IAAc,OAAO;IAAQ,MAAK;IAAM,SAAS,QAAQ,GAAG;GAAI,CAAA,IAAI;GAC7E;EACE;;AAET"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region resources/js/ui/avatar.tsx
|
|
4
|
+
var sizeClass = {
|
|
5
|
+
xs: "size-6 text-[0.5rem]",
|
|
6
|
+
sm: "size-8 text-xs",
|
|
7
|
+
md: "size-10 text-sm",
|
|
8
|
+
lg: "size-12 text-base",
|
|
9
|
+
xl: "size-16 text-lg",
|
|
10
|
+
"2xl": "size-20 text-xl",
|
|
11
|
+
"3xl": "size-24 text-2xl",
|
|
12
|
+
"4xl": "size-32 text-3xl"
|
|
13
|
+
};
|
|
14
|
+
function initials(name) {
|
|
15
|
+
return name.trim().split(/\s+/).slice(0, 2).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
16
|
+
}
|
|
17
|
+
function UserGlyph() {
|
|
18
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
19
|
+
viewBox: "0 0 24 24",
|
|
20
|
+
fill: "none",
|
|
21
|
+
stroke: "currentColor",
|
|
22
|
+
strokeWidth: 2,
|
|
23
|
+
strokeLinecap: "round",
|
|
24
|
+
strokeLinejoin: "round",
|
|
25
|
+
"aria-hidden": "true",
|
|
26
|
+
className: "size-[60%]",
|
|
27
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" }), /* @__PURE__ */ jsx("circle", {
|
|
28
|
+
cx: "12",
|
|
29
|
+
cy: "7",
|
|
30
|
+
r: "4"
|
|
31
|
+
})]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
var AvatarComponent = ({ node }) => {
|
|
35
|
+
const { src, name, size } = node.props;
|
|
36
|
+
const label = name ?? void 0;
|
|
37
|
+
return /* @__PURE__ */ jsx("span", {
|
|
38
|
+
"data-slot": "avatar",
|
|
39
|
+
role: src ? void 0 : "img",
|
|
40
|
+
"aria-label": src ? void 0 : label,
|
|
41
|
+
className: cn("inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-lt-muted font-medium text-lt-muted-fg select-none", sizeClass[size]),
|
|
42
|
+
children: src ? /* @__PURE__ */ jsx("img", {
|
|
43
|
+
src,
|
|
44
|
+
alt: label ?? "",
|
|
45
|
+
className: "size-full object-cover"
|
|
46
|
+
}) : name ? initials(name) : /* @__PURE__ */ jsx(UserGlyph, {})
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { AvatarComponent as default };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar.js","names":[],"sources":["../../resources/js/ui/avatar.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Size } from \"@lattice-php/lattice/types/generated\";\n\nconst sizeClass: Record<Size, string> = {\n xs: \"size-6 text-[0.5rem]\",\n sm: \"size-8 text-xs\",\n md: \"size-10 text-sm\",\n lg: \"size-12 text-base\",\n xl: \"size-16 text-lg\",\n \"2xl\": \"size-20 text-xl\",\n \"3xl\": \"size-24 text-2xl\",\n \"4xl\": \"size-32 text-3xl\",\n};\n\nfunction initials(name: string): string {\n return name\n .trim()\n .split(/\\s+/)\n .slice(0, 2)\n .map((word) => word.charAt(0).toUpperCase())\n .join(\"\");\n}\n\nfunction UserGlyph() {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className=\"size-[60%]\"\n >\n <path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\" />\n <circle cx=\"12\" cy=\"7\" r=\"4\" />\n </svg>\n );\n}\n\nconst AvatarComponent: RendererComponent<\"avatar\"> = ({ node }) => {\n const { src, name, size } = node.props;\n const label = name ?? undefined;\n\n return (\n <span\n data-slot=\"avatar\"\n role={src ? undefined : \"img\"}\n aria-label={src ? undefined : label}\n className={cn(\n \"inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-lt-muted font-medium text-lt-muted-fg select-none\",\n sizeClass[size],\n )}\n >\n {src ? (\n <img src={src} alt={label ?? \"\"} className=\"size-full object-cover\" />\n ) : name ? (\n initials(name)\n ) : (\n <UserGlyph />\n )}\n </span>\n );\n};\n\nexport default AvatarComponent;\n"],"mappings":";;;AAIA,IAAM,YAAkC;CACtC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,SAAS,SAAS,MAAsB;CACtC,OAAO,KACJ,KAAK,EACL,MAAM,KAAK,EACX,MAAM,GAAG,CAAC,EACV,KAAK,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,CAAC,EAC1C,KAAK,EAAE;AACZ;AAEA,SAAS,YAAY;CACnB,OACE,qBAAC,OAAD;EACE,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAa;EACb,eAAc;EACd,gBAAe;EACf,eAAY;EACZ,WAAU;YARZ,CAUE,oBAAC,QAAD,EAAM,GAAE,4CAA6C,CAAA,GACrD,oBAAC,UAAD;GAAQ,IAAG;GAAK,IAAG;GAAI,GAAE;EAAK,CAAA,CAC3B;;AAET;AAEA,IAAM,mBAAgD,EAAE,WAAW;CACjE,MAAM,EAAE,KAAK,MAAM,SAAS,KAAK;CACjC,MAAM,QAAQ,QAAQ,KAAA;CAEtB,OACE,oBAAC,QAAD;EACE,aAAU;EACV,MAAM,MAAM,KAAA,IAAY;EACxB,cAAY,MAAM,KAAA,IAAY;EAC9B,WAAW,GACT,sIACA,UAAU,KACZ;YAEC,MACC,oBAAC,OAAD;GAAU;GAAK,KAAK,SAAS;GAAI,WAAU;EAA0B,CAAA,IACnE,OACF,SAAS,IAAI,IAEb,oBAAC,WAAD,CAAY,CAAA;CAEV,CAAA;AAEV"}
|
package/dist/ui/button.d.ts
CHANGED
|
@@ -7,8 +7,10 @@ declare const buttonVariants: (props?: ({
|
|
|
7
7
|
variant?: "default" | "destructive" | "ghost" | "info" | "link" | "outline" | "secondary" | "success" | null | undefined;
|
|
8
8
|
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
9
9
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
10
|
-
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
|
10
|
+
declare function Button({ className, variant, size, asChild, icon, children, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
|
11
11
|
asChild?: boolean;
|
|
12
|
+
/** Leading icon glyph. Ignored with `asChild` (Slot needs a single child). */
|
|
13
|
+
icon?: string;
|
|
12
14
|
}): React.JSX.Element;
|
|
13
15
|
declare const ButtonComponent: RendererComponent<"button">;
|
|
14
16
|
export default ButtonComponent;
|
package/dist/ui/button.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { Icon } from "../icons/sprite.js";
|
|
2
3
|
import { IconRenderer } from "../icons/icon-renderer.js";
|
|
3
4
|
import { nodeIdentity } from "../core/test-id.js";
|
|
4
5
|
import { ActionTrigger, useClickBehavior } from "./click-behavior.js";
|
|
@@ -32,15 +33,21 @@ var buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespa
|
|
|
32
33
|
size: "default"
|
|
33
34
|
}
|
|
34
35
|
});
|
|
35
|
-
function Button({ className, variant, size, asChild = false, ...props }) {
|
|
36
|
-
|
|
36
|
+
function Button({ className, variant, size, asChild = false, icon, children, ...props }) {
|
|
37
|
+
const Comp = asChild ? Slot : "button";
|
|
38
|
+
const content = icon && !asChild ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Icon, {
|
|
39
|
+
name: icon,
|
|
40
|
+
"aria-hidden": "true"
|
|
41
|
+
}), children] }) : children;
|
|
42
|
+
return /* @__PURE__ */ jsx(Comp, {
|
|
37
43
|
"data-slot": "button",
|
|
38
44
|
className: cn(buttonVariants({
|
|
39
45
|
variant,
|
|
40
46
|
size,
|
|
41
47
|
className
|
|
42
48
|
})),
|
|
43
|
-
...props
|
|
49
|
+
...props,
|
|
50
|
+
children: content
|
|
44
51
|
});
|
|
45
52
|
}
|
|
46
53
|
var ButtonComponent = ({ node }) => {
|
package/dist/ui/button.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","names":[],"sources":["../../resources/js/ui/button.tsx"],"sourcesContent":["import { Link } from \"@inertiajs/react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { ActionTrigger, type TriggerState, useClickBehavior } from \"./click-behavior\";\nimport type { ButtonVariant } from \"@lattice-php/lattice/types/generated\";\n\nexport type { ButtonVariant };\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lt-sm text-base font-medium transition-[color,box-shadow] disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-lt-icon-md [&_svg]:shrink-0 outline-none focus-visible:border-lt-ring focus-visible:ring-lt-ring/50 focus-visible:ring-[3px] aria-invalid:ring-lt-danger/20 dark:aria-invalid:ring-lt-danger/40 aria-invalid:border-lt-danger\",\n {\n variants: {\n variant: {\n default:\n \"bg-lt-primary text-lt-primary-fg shadow-lt-xs hover:bg-lt-primary-hover active:bg-lt-primary-active disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n destructive:\n \"bg-lt-danger text-lt-danger-fg shadow-lt-xs hover:bg-lt-danger-hover active:bg-lt-danger-active focus-visible:ring-lt-danger/20 dark:focus-visible:ring-lt-danger/40 disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n success:\n \"bg-lt-success text-lt-success-fg shadow-lt-xs hover:bg-lt-success-hover active:bg-lt-success-active disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n info: \"bg-lt-info text-lt-info-fg shadow-lt-xs hover:bg-lt-info-hover active:bg-lt-info-active disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n outline:\n \"border border-lt-input bg-lt-bg shadow-lt-xs hover:bg-lt-accent hover:text-lt-accent-fg disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:border-transparent disabled:shadow-none\",\n secondary:\n \"bg-lt-secondary text-lt-secondary-fg shadow-lt-xs hover:bg-lt-secondary-hover active:bg-lt-secondary-active disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n ghost: \"hover:bg-lt-accent hover:text-lt-accent-fg disabled:text-lt-disabled-fg\",\n link: \"text-lt-primary underline-offset-4 hover:underline disabled:text-lt-disabled-fg disabled:no-underline\",\n },\n size: {\n default: \"h-lt-control-md px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-lt-control-sm rounded-lt-sm px-3 has-[>svg]:px-2.5\",\n lg: \"h-lt-control-lg rounded-lt-sm px-6 has-[>svg]:px-4\",\n icon: \"size-lt-control-md\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n
|
|
1
|
+
{"version":3,"file":"button.js","names":[],"sources":["../../resources/js/ui/button.tsx"],"sourcesContent":["import { Link } from \"@inertiajs/react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Icon, IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { ActionTrigger, type TriggerState, useClickBehavior } from \"./click-behavior\";\nimport type { ButtonVariant } from \"@lattice-php/lattice/types/generated\";\n\nexport type { ButtonVariant };\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lt-sm text-base font-medium transition-[color,box-shadow] disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-lt-icon-md [&_svg]:shrink-0 outline-none focus-visible:border-lt-ring focus-visible:ring-lt-ring/50 focus-visible:ring-[3px] aria-invalid:ring-lt-danger/20 dark:aria-invalid:ring-lt-danger/40 aria-invalid:border-lt-danger\",\n {\n variants: {\n variant: {\n default:\n \"bg-lt-primary text-lt-primary-fg shadow-lt-xs hover:bg-lt-primary-hover active:bg-lt-primary-active disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n destructive:\n \"bg-lt-danger text-lt-danger-fg shadow-lt-xs hover:bg-lt-danger-hover active:bg-lt-danger-active focus-visible:ring-lt-danger/20 dark:focus-visible:ring-lt-danger/40 disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n success:\n \"bg-lt-success text-lt-success-fg shadow-lt-xs hover:bg-lt-success-hover active:bg-lt-success-active disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n info: \"bg-lt-info text-lt-info-fg shadow-lt-xs hover:bg-lt-info-hover active:bg-lt-info-active disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n outline:\n \"border border-lt-input bg-lt-bg shadow-lt-xs hover:bg-lt-accent hover:text-lt-accent-fg disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:border-transparent disabled:shadow-none\",\n secondary:\n \"bg-lt-secondary text-lt-secondary-fg shadow-lt-xs hover:bg-lt-secondary-hover active:bg-lt-secondary-active disabled:bg-lt-disabled disabled:text-lt-disabled-fg disabled:shadow-none\",\n ghost: \"hover:bg-lt-accent hover:text-lt-accent-fg disabled:text-lt-disabled-fg\",\n link: \"text-lt-primary underline-offset-4 hover:underline disabled:text-lt-disabled-fg disabled:no-underline\",\n },\n size: {\n default: \"h-lt-control-md px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-lt-control-sm rounded-lt-sm px-3 has-[>svg]:px-2.5\",\n lg: \"h-lt-control-lg rounded-lt-sm px-6 has-[>svg]:px-4\",\n icon: \"size-lt-control-md\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n icon,\n children,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n /** Leading icon glyph. Ignored with `asChild` (Slot needs a single child). */\n icon?: string;\n }) {\n const Comp = asChild ? Slot : \"button\";\n const content =\n icon && !asChild ? (\n <>\n <Icon name={icon} aria-hidden=\"true\" />\n {children}\n </>\n ) : (\n children\n );\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n >\n {content}\n </Comp>\n );\n}\n\nconst ButtonComponent: RendererComponent<\"button\"> = ({ node }) => {\n const { label, icon } = node.props;\n const variant = node.props.variant ?? \"default\";\n const testId = nodeIdentity(node);\n const behavior = useClickBehavior(node.props);\n const size = icon ? \"icon\" : \"default\";\n const content = icon ? (\n <>\n <IconRenderer className=\"size-lt-icon-md\" icon={icon} />\n {label ? <span className=\"sr-only\">{label}</span> : null}\n </>\n ) : (\n label\n );\n\n const triggerButton = ({ onClick, processing }: TriggerState) => (\n <Button\n data-test={testId}\n disabled={processing}\n onClick={onClick}\n size={size}\n variant={variant}\n >\n {content}\n </Button>\n );\n\n if (behavior.kind === \"navigate\") {\n return (\n <Button asChild data-test={testId} variant={variant} size={size}>\n <Link href={behavior.href} method={behavior.method}>\n {content}\n </Link>\n </Button>\n );\n }\n\n if (behavior.kind === \"action\") {\n return <ActionTrigger action={behavior.action}>{triggerButton}</ActionTrigger>;\n }\n\n if (behavior.kind === \"effects\") {\n return triggerButton({ onClick: behavior.onClick, processing: false });\n }\n\n return (\n <Button data-test={testId} size={size} type={node.props.buttonType} variant={variant}>\n {content}\n </Button>\n );\n};\n\nexport default ButtonComponent;\nexport { Button, buttonVariants };\n"],"mappings":";;;;;;;;;;;AAaA,IAAM,iBAAiB,IACrB,+bACA;CACE,UAAU;EACR,SAAS;GACP,SACE;GACF,aACE;GACF,SACE;GACF,MAAM;GACN,SACE;GACF,WACE;GACF,OAAO;GACP,MAAM;EACR;EACA,MAAM;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,MAAM;EACR;CACF;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;CACR;AACF,CACF;AAEA,SAAS,OAAO,EACd,WACA,SACA,MACA,UAAU,OACV,MACA,UACA,GAAG,SAMA;CACH,MAAM,OAAO,UAAU,OAAO;CAC9B,MAAM,UACJ,QAAQ,CAAC,UACP,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,MAAD;EAAM,MAAM;EAAM,eAAY;CAAQ,CAAA,GACrC,QACD,EAAA,CAAA,IAEF;CAGJ,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GAAG,eAAe;GAAE;GAAS;GAAM;EAAU,CAAC,CAAC;EAC1D,GAAI;YAEH;CACG,CAAA;AAEV;AAEA,IAAM,mBAAgD,EAAE,WAAW;CACjE,MAAM,EAAE,OAAO,SAAS,KAAK;CAC7B,MAAM,UAAU,KAAK,MAAM,WAAW;CACtC,MAAM,SAAS,aAAa,IAAI;CAChC,MAAM,WAAW,iBAAiB,KAAK,KAAK;CAC5C,MAAM,OAAO,OAAO,SAAS;CAC7B,MAAM,UAAU,OACd,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,cAAD;EAAc,WAAU;EAAwB;CAAO,CAAA,GACtD,QAAQ,oBAAC,QAAD;EAAM,WAAU;YAAW;CAAY,CAAA,IAAI,IACpD,EAAA,CAAA,IAEF;CAGF,MAAM,iBAAiB,EAAE,SAAS,iBAChC,oBAAC,QAAD;EACE,aAAW;EACX,UAAU;EACD;EACH;EACG;YAER;CACK,CAAA;CAGV,IAAI,SAAS,SAAS,YACpB,OACE,oBAAC,QAAD;EAAQ,SAAA;EAAQ,aAAW;EAAiB;EAAe;YACzD,oBAAC,MAAD;GAAM,MAAM,SAAS;GAAM,QAAQ,SAAS;aACzC;EACG,CAAA;CACA,CAAA;CAIZ,IAAI,SAAS,SAAS,UACpB,OAAO,oBAAC,eAAD;EAAe,QAAQ,SAAS;YAAS;CAA6B,CAAA;CAG/E,IAAI,SAAS,SAAS,WACpB,OAAO,cAAc;EAAE,SAAS,SAAS;EAAS,YAAY;CAAM,CAAC;CAGvE,OACE,oBAAC,QAAD;EAAQ,aAAW;EAAc;EAAM,MAAM,KAAK,MAAM;EAAqB;YAC1E;CACK,CAAA;AAEZ"}
|
package/dist/ui/chart-view.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { useLocale } from "../i18n/locale.js";
|
|
2
2
|
import { useTimezone } from "../i18n/timezone.js";
|
|
3
3
|
import { nodeIdentity } from "../core/test-id.js";
|
|
4
|
+
import { coerceColor, colorValue } from "../lib/color.js";
|
|
5
|
+
import { numericValue } from "../format/numeric.js";
|
|
4
6
|
import { formatValue } from "../format/value.js";
|
|
5
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, ComposedChart, Legend, Line, LineChart, Pie, PieChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
|
|
8
|
+
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, ComposedChart, Legend, Line, LineChart, Pie, PieChart, PolarAngleAxis, RadialBar, RadialBarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
|
|
7
9
|
//#region resources/js/ui/chart-view.tsx
|
|
8
10
|
var chartMargin = {
|
|
9
11
|
bottom: 0,
|
|
@@ -50,12 +52,26 @@ function isRecord(value) {
|
|
|
50
52
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
51
53
|
}
|
|
52
54
|
function datumColor(datum, series, index) {
|
|
53
|
-
if (isRecord(datum)
|
|
54
|
-
|
|
55
|
+
if (isRecord(datum)) {
|
|
56
|
+
const color = coerceColor(datum.color);
|
|
57
|
+
if (color) return colorValue(color);
|
|
58
|
+
}
|
|
59
|
+
return series.color ? colorValue(series.color) : colorAt(index);
|
|
55
60
|
}
|
|
56
61
|
function isCartesianSeries(series) {
|
|
57
62
|
return series.type === "area" || series.type === "bar" || series.type === "line";
|
|
58
63
|
}
|
|
64
|
+
function isSpecialSeries(series) {
|
|
65
|
+
return !isCartesianSeries(series);
|
|
66
|
+
}
|
|
67
|
+
function datumValue(datum, key) {
|
|
68
|
+
return isRecord(datum) ? numericValue(datum[key]) ?? 0 : 0;
|
|
69
|
+
}
|
|
70
|
+
function datumName(datum, series) {
|
|
71
|
+
if (series.nameKey === null || !isRecord(datum)) return series.name;
|
|
72
|
+
const name = datum[series.nameKey];
|
|
73
|
+
return typeof name === "string" ? name : series.name;
|
|
74
|
+
}
|
|
59
75
|
function cartesianChartFor(series) {
|
|
60
76
|
const types = new Set(series.map((item) => item.type));
|
|
61
77
|
const firstSeries = series[0];
|
|
@@ -134,13 +150,13 @@ function CartesianChart({ props }) {
|
|
|
134
150
|
}),
|
|
135
151
|
props.legend && /* @__PURE__ */ jsx(Legend, { ...compactLegendProps }),
|
|
136
152
|
series.map((item, index) => {
|
|
137
|
-
const color = item.color
|
|
153
|
+
const color = item.color ? colorValue(item.color) : colorAt(index);
|
|
138
154
|
const key = `${item.type}:${item.dataKey}`;
|
|
139
155
|
if (item.type === "area") return /* @__PURE__ */ jsx(Area, {
|
|
140
156
|
dataKey: item.dataKey,
|
|
141
157
|
fill: color,
|
|
142
158
|
fillOpacity: .16,
|
|
143
|
-
name: item.name
|
|
159
|
+
name: item.name,
|
|
144
160
|
stackId: item.stackId ?? void 0,
|
|
145
161
|
stroke: color,
|
|
146
162
|
type: "monotone"
|
|
@@ -148,7 +164,7 @@ function CartesianChart({ props }) {
|
|
|
148
164
|
if (item.type === "bar") return /* @__PURE__ */ jsx(Bar, {
|
|
149
165
|
dataKey: item.dataKey,
|
|
150
166
|
fill: color,
|
|
151
|
-
name: item.name
|
|
167
|
+
name: item.name,
|
|
152
168
|
radius: [
|
|
153
169
|
4,
|
|
154
170
|
4,
|
|
@@ -160,7 +176,7 @@ function CartesianChart({ props }) {
|
|
|
160
176
|
return /* @__PURE__ */ jsx(Line, {
|
|
161
177
|
dataKey: item.dataKey,
|
|
162
178
|
dot: false,
|
|
163
|
-
name: item.name
|
|
179
|
+
name: item.name,
|
|
164
180
|
stroke: color,
|
|
165
181
|
strokeWidth: 2,
|
|
166
182
|
type: "monotone"
|
|
@@ -193,8 +209,9 @@ function PieChartView({ props, series }) {
|
|
|
193
209
|
/* @__PURE__ */ jsx(Pie, {
|
|
194
210
|
data: props.data,
|
|
195
211
|
dataKey: series.dataKey,
|
|
196
|
-
name: series.name
|
|
212
|
+
name: series.name,
|
|
197
213
|
nameKey: series.nameKey ?? void 0,
|
|
214
|
+
innerRadius: series.innerRadius,
|
|
198
215
|
outerRadius: "68%",
|
|
199
216
|
children: props.data.map((datum, index) => /* @__PURE__ */ jsx(Cell, { fill: datumColor(datum, series, index) }, index))
|
|
200
217
|
})
|
|
@@ -202,9 +219,142 @@ function PieChartView({ props, series }) {
|
|
|
202
219
|
})
|
|
203
220
|
});
|
|
204
221
|
}
|
|
222
|
+
function ChartLegend({ entries }) {
|
|
223
|
+
return /* @__PURE__ */ jsx("div", {
|
|
224
|
+
className: "flex flex-wrap items-center justify-center gap-x-3 gap-y-1",
|
|
225
|
+
children: entries.map((entry, index) => /* @__PURE__ */ jsxs("span", {
|
|
226
|
+
className: "flex items-center gap-1 text-[11px] leading-[14px] text-lt-muted-fg",
|
|
227
|
+
children: [
|
|
228
|
+
/* @__PURE__ */ jsx("span", {
|
|
229
|
+
"aria-hidden": true,
|
|
230
|
+
className: "size-[7px] rounded-full",
|
|
231
|
+
style: { background: entry.color }
|
|
232
|
+
}),
|
|
233
|
+
entry.label,
|
|
234
|
+
entry.value !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
235
|
+
className: "font-medium text-lt-surface-fg",
|
|
236
|
+
children: entry.value
|
|
237
|
+
})
|
|
238
|
+
]
|
|
239
|
+
}, index))
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
function GaugeChartView({ props, series }) {
|
|
243
|
+
const { locale } = useLocale();
|
|
244
|
+
const { timezone } = useTimezone();
|
|
245
|
+
const ctx = {
|
|
246
|
+
locale,
|
|
247
|
+
timezone
|
|
248
|
+
};
|
|
249
|
+
const values = props.data.map((datum) => datumValue(datum, series.dataKey));
|
|
250
|
+
const max = series.maxValue ?? Math.max(0, ...values);
|
|
251
|
+
const legendEntries = props.data.map((datum, index) => ({
|
|
252
|
+
color: datumColor(datum, series, index),
|
|
253
|
+
label: datumName(datum, series)
|
|
254
|
+
}));
|
|
255
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
256
|
+
className: "flex flex-col gap-1.5",
|
|
257
|
+
children: [props.legend && /* @__PURE__ */ jsx(ChartLegend, { entries: legendEntries }), /* @__PURE__ */ jsxs("div", {
|
|
258
|
+
className: "relative",
|
|
259
|
+
children: [/* @__PURE__ */ jsx(ResponsiveContainer, {
|
|
260
|
+
width: "100%",
|
|
261
|
+
height: props.height,
|
|
262
|
+
debounce: 100,
|
|
263
|
+
children: /* @__PURE__ */ jsxs(RadialBarChart, {
|
|
264
|
+
data: props.data,
|
|
265
|
+
endAngle: -30,
|
|
266
|
+
innerRadius: series.innerRadius,
|
|
267
|
+
margin: chartMargin,
|
|
268
|
+
outerRadius: "100%",
|
|
269
|
+
startAngle: 210,
|
|
270
|
+
children: [
|
|
271
|
+
/* @__PURE__ */ jsx(PolarAngleAxis, {
|
|
272
|
+
type: "number",
|
|
273
|
+
domain: [0, max],
|
|
274
|
+
tick: false
|
|
275
|
+
}),
|
|
276
|
+
props.tooltip && /* @__PURE__ */ jsx(Tooltip, {
|
|
277
|
+
...tooltipProps,
|
|
278
|
+
formatter: (value) => formatValue(value, props.valueFormat, ctx)
|
|
279
|
+
}),
|
|
280
|
+
/* @__PURE__ */ jsx(RadialBar, {
|
|
281
|
+
background: { fill: "var(--lt-muted)" },
|
|
282
|
+
cornerRadius: 6,
|
|
283
|
+
dataKey: series.dataKey,
|
|
284
|
+
name: series.name,
|
|
285
|
+
children: props.data.map((datum, index) => /* @__PURE__ */ jsx(Cell, { fill: datumColor(datum, series, index) }, index))
|
|
286
|
+
})
|
|
287
|
+
]
|
|
288
|
+
})
|
|
289
|
+
}), values.length === 1 && /* @__PURE__ */ jsx("div", {
|
|
290
|
+
className: "pointer-events-none absolute inset-0 flex items-center justify-center",
|
|
291
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
292
|
+
className: "text-2xl font-semibold text-lt-surface-fg",
|
|
293
|
+
children: formatValue(values[0], props.valueFormat, ctx)
|
|
294
|
+
})
|
|
295
|
+
})]
|
|
296
|
+
})]
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function DistributionChartView({ props, series }) {
|
|
300
|
+
const { locale } = useLocale();
|
|
301
|
+
const { timezone } = useTimezone();
|
|
302
|
+
const ctx = {
|
|
303
|
+
locale,
|
|
304
|
+
timezone
|
|
305
|
+
};
|
|
306
|
+
const segments = props.data.map((datum, index) => ({
|
|
307
|
+
color: datumColor(datum, series, index),
|
|
308
|
+
label: datumName(datum, series),
|
|
309
|
+
value: datumValue(datum, series.dataKey)
|
|
310
|
+
})).filter((segment) => segment.value > 0);
|
|
311
|
+
const total = segments.reduce((sum, segment) => sum + segment.value, 0);
|
|
312
|
+
if (total <= 0) return /* @__PURE__ */ jsx("div", {
|
|
313
|
+
className: "h-2.5 w-full rounded-full bg-lt-muted",
|
|
314
|
+
"data-lattice-distribution": ""
|
|
315
|
+
});
|
|
316
|
+
const formatPercent = new Intl.NumberFormat(locale, {
|
|
317
|
+
maximumFractionDigits: 1,
|
|
318
|
+
style: "percent"
|
|
319
|
+
});
|
|
320
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
321
|
+
className: "flex flex-col gap-1.5",
|
|
322
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
323
|
+
className: "flex h-2.5 w-full gap-0.5 overflow-hidden rounded-full",
|
|
324
|
+
"data-lattice-distribution": "",
|
|
325
|
+
children: segments.map((segment, index) => /* @__PURE__ */ jsx("div", {
|
|
326
|
+
style: {
|
|
327
|
+
background: segment.color,
|
|
328
|
+
width: `${segment.value / total * 100}%`
|
|
329
|
+
},
|
|
330
|
+
title: props.tooltip ? `${segment.label}: ${formatValue(segment.value, props.valueFormat, ctx)}` : void 0
|
|
331
|
+
}, index))
|
|
332
|
+
}), props.legend && /* @__PURE__ */ jsx(ChartLegend, { entries: segments.map((segment) => ({
|
|
333
|
+
color: segment.color,
|
|
334
|
+
label: segment.label,
|
|
335
|
+
value: formatPercent.format(segment.value / total)
|
|
336
|
+
})) })]
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
function SpecialChart({ props, series }) {
|
|
340
|
+
switch (series.type) {
|
|
341
|
+
case "distribution": return /* @__PURE__ */ jsx(DistributionChartView, {
|
|
342
|
+
props,
|
|
343
|
+
series
|
|
344
|
+
});
|
|
345
|
+
case "gauge": return /* @__PURE__ */ jsx(GaugeChartView, {
|
|
346
|
+
props,
|
|
347
|
+
series
|
|
348
|
+
});
|
|
349
|
+
case "pie": return /* @__PURE__ */ jsx(PieChartView, {
|
|
350
|
+
props,
|
|
351
|
+
series
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
205
355
|
var ChartView = ({ node }) => {
|
|
206
356
|
const props = node.props;
|
|
207
|
-
const
|
|
357
|
+
const specialSeries = props.series.find(isSpecialSeries);
|
|
208
358
|
const hasCartesianSeries = props.series.some(isCartesianSeries);
|
|
209
359
|
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
210
360
|
description: props.description,
|
|
@@ -212,9 +362,9 @@ var ChartView = ({ node }) => {
|
|
|
212
362
|
title: props.title,
|
|
213
363
|
children: /* @__PURE__ */ jsx("div", {
|
|
214
364
|
className: "min-h-0 w-full",
|
|
215
|
-
children:
|
|
365
|
+
children: specialSeries !== void 0 && !hasCartesianSeries ? /* @__PURE__ */ jsx(SpecialChart, {
|
|
216
366
|
props,
|
|
217
|
-
series:
|
|
367
|
+
series: specialSeries
|
|
218
368
|
}) : /* @__PURE__ */ jsx(CartesianChart, { props })
|
|
219
369
|
})
|
|
220
370
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-view.js","names":[],"sources":["../../resources/js/ui/chart-view.tsx"],"sourcesContent":["import {\n Area,\n AreaChart,\n Bar,\n BarChart,\n CartesianGrid,\n Cell,\n ComposedChart,\n Legend,\n Line,\n LineChart,\n Pie,\n PieChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport type { ComponentType, ReactNode } from \"react\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport type { PropsOf, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useLocale, useTimezone } from \"@lattice-php/lattice/i18n\";\nimport { formatValue } from \"@lattice-php/lattice/format/value\";\n\ntype ChartProps = PropsOf<\"chart\">;\ntype ChartSeries = ChartProps[\"series\"][number];\ntype ChartDatum = ChartProps[\"data\"][number];\ntype CartesianSeries = ChartSeries & { type: \"area\" | \"bar\" | \"line\" };\ntype ChartMargin = { bottom: number; left: number; right: number; top: number };\ntype CartesianChartComponent = ComponentType<{\n children: ReactNode;\n data: ChartProps[\"data\"];\n margin?: ChartMargin;\n}>;\n\nconst chartMargin: ChartMargin = { bottom: 0, left: 0, right: 16, top: 8 };\nconst compactLegendProps = {\n align: \"center\" as const,\n height: 24,\n iconSize: 7,\n verticalAlign: \"top\" as const,\n wrapperStyle: { fontSize: 11, lineHeight: \"14px\", paddingBottom: 6 },\n};\nconst axisTick = { fontSize: 10 };\nconst tooltipProps = {\n contentStyle: {\n background: \"var(--lt-surface)\",\n border: \"1px solid var(--lt-border)\",\n borderRadius: \"var(--lt-radius-sm)\",\n boxShadow: \"var(--lt-shadow-sm)\",\n color: \"var(--lt-surface-fg)\",\n fontSize: 12,\n },\n itemStyle: { color: \"var(--lt-surface-fg)\" },\n labelStyle: { color: \"var(--lt-muted-fg)\" },\n} as const;\n\nconst palette = [\n \"var(--lt-primary)\",\n \"var(--lt-success)\",\n \"var(--lt-info)\",\n \"var(--lt-warning)\",\n \"var(--lt-danger)\",\n \"var(--lt-muted-fg)\",\n];\n\nfunction colorAt(index: number): string {\n return palette[index % palette.length] ?? \"var(--lt-primary)\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction datumColor(datum: ChartDatum, series: ChartSeries, index: number): string {\n if (isRecord(datum) && typeof datum.color === \"string\") {\n return datum.color;\n }\n\n return series.color ?? colorAt(index);\n}\n\nfunction isCartesianSeries(series: ChartSeries): series is CartesianSeries {\n return series.type === \"area\" || series.type === \"bar\" || series.type === \"line\";\n}\n\nfunction cartesianChartFor(series: CartesianSeries[]): CartesianChartComponent {\n const types = new Set(series.map((item) => item.type));\n const firstSeries = series[0];\n\n if (firstSeries === undefined || types.size !== 1) {\n return ComposedChart;\n }\n\n switch (firstSeries.type) {\n case \"area\":\n return AreaChart;\n case \"bar\":\n return BarChart;\n case \"line\":\n return LineChart;\n }\n}\n\nfunction ChartFrame({\n children,\n description,\n id,\n title,\n}: {\n children: ReactNode;\n description: string | null;\n id?: string;\n title: string | null;\n}) {\n const hasHeader = title !== null || description !== null;\n\n return (\n <div\n className=\"flex flex-col gap-3 rounded-lt border border-lt-border bg-lt-surface p-4 text-lt-surface-fg shadow-lt-sm\"\n data-lattice-component={id}\n >\n {hasHeader && (\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n {title !== null && <div className=\"text-sm font-semibold leading-tight\">{title}</div>}\n {description !== null && (\n <div className=\"text-xs leading-5 text-lt-muted-fg\">{description}</div>\n )}\n </div>\n )}\n {children}\n </div>\n );\n}\n\nfunction CartesianChart({ props }: { props: ChartProps }) {\n const series = props.series.filter(isCartesianSeries);\n const RechartsChart = cartesianChartFor(series);\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n const ctx = { locale, timezone };\n const formatCategory = (value: unknown) => formatValue(value, props.categoryFormat, ctx);\n const formatValueTick = (value: unknown) => formatValue(value, props.valueFormat, ctx);\n const hasBarSeries = series.some((item) => item.type === \"bar\");\n const tooltipCursor = hasBarSeries\n ? { fill: \"var(--lt-muted-fg)\", fillOpacity: 0.15 }\n : { stroke: \"var(--lt-muted-fg)\", strokeOpacity: 0.4 };\n\n return (\n <ResponsiveContainer width=\"100%\" height={props.height} debounce={100}>\n <RechartsChart data={props.data} margin={chartMargin}>\n {props.grid && <CartesianGrid strokeDasharray=\"3 3\" stroke=\"var(--lt-border)\" />}\n {props.xAxis && props.categoryKey !== null && (\n <XAxis\n dataKey={props.categoryKey}\n stroke=\"var(--lt-muted-fg)\"\n tick={axisTick}\n tickFormatter={formatCategory}\n tickLine={false}\n />\n )}\n {props.yAxis && (\n <YAxis\n stroke=\"var(--lt-muted-fg)\"\n tick={axisTick}\n tickFormatter={formatValueTick}\n tickLine={false}\n width={42}\n />\n )}\n {props.tooltip && (\n <Tooltip\n {...tooltipProps}\n cursor={tooltipCursor}\n formatter={formatValueTick}\n labelFormatter={formatCategory}\n />\n )}\n {props.legend && <Legend {...compactLegendProps} />}\n {series.map((item, index) => {\n const color = item.color ?? colorAt(index);\n const key = `${item.type}:${item.dataKey}`;\n\n if (item.type === \"area\") {\n return (\n <Area\n key={key}\n dataKey={item.dataKey}\n fill={color}\n fillOpacity={0.16}\n name={item.name ?? undefined}\n stackId={item.stackId ?? undefined}\n stroke={color}\n type=\"monotone\"\n />\n );\n }\n\n if (item.type === \"bar\") {\n return (\n <Bar\n key={key}\n dataKey={item.dataKey}\n fill={color}\n name={item.name ?? undefined}\n radius={[4, 4, 0, 0]}\n stackId={item.stackId ?? undefined}\n />\n );\n }\n\n return (\n <Line\n key={key}\n dataKey={item.dataKey}\n dot={false}\n name={item.name ?? undefined}\n stroke={color}\n strokeWidth={2}\n type=\"monotone\"\n />\n );\n })}\n </RechartsChart>\n </ResponsiveContainer>\n );\n}\n\nfunction PieChartView({ props, series }: { props: ChartProps; series: ChartSeries }) {\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n const ctx = { locale, timezone };\n\n return (\n <ResponsiveContainer width=\"100%\" height={props.height} debounce={100}>\n <PieChart margin={chartMargin}>\n {props.tooltip && (\n <Tooltip\n {...tooltipProps}\n formatter={(value) => formatValue(value, props.valueFormat, ctx)}\n labelFormatter={(value) => formatValue(value, props.categoryFormat, ctx)}\n />\n )}\n {props.legend && <Legend {...compactLegendProps} />}\n <Pie\n data={props.data}\n dataKey={series.dataKey}\n name={series.name ?? undefined}\n nameKey={series.nameKey ?? undefined}\n outerRadius=\"68%\"\n >\n {props.data.map((datum, index) => (\n <Cell key={index} fill={datumColor(datum, series, index)} />\n ))}\n </Pie>\n </PieChart>\n </ResponsiveContainer>\n );\n}\n\nconst ChartView: RendererComponent<\"chart\"> = ({ node }) => {\n const props = node.props;\n const pieSeries = props.series.find((series) => series.type === \"pie\");\n const hasCartesianSeries = props.series.some(isCartesianSeries);\n\n return (\n <ChartFrame description={props.description} id={nodeIdentity(node)} title={props.title}>\n <div className=\"min-h-0 w-full\">\n {pieSeries && !hasCartesianSeries ? (\n <PieChartView props={props} series={pieSeries} />\n ) : (\n <CartesianChart props={props} />\n )}\n </div>\n </ChartFrame>\n );\n};\n\nexport default ChartView;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-view.js","names":[],"sources":["../../resources/js/ui/chart-view.tsx"],"sourcesContent":["import {\n Area,\n AreaChart,\n Bar,\n BarChart,\n CartesianGrid,\n Cell,\n ComposedChart,\n Legend,\n Line,\n LineChart,\n Pie,\n PieChart,\n PolarAngleAxis,\n RadialBar,\n RadialBarChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport type { ComponentType, ReactNode } from \"react\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport type { PropsOf, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { coerceColor, colorValue } from \"@lattice-php/lattice/lib/color\";\nimport { useLocale, useTimezone } from \"@lattice-php/lattice/i18n\";\nimport { numericValue } from \"@lattice-php/lattice/format/numeric\";\nimport { formatValue } from \"@lattice-php/lattice/format/value\";\n\ntype ChartProps = PropsOf<\"chart\">;\ntype ChartSeries = ChartProps[\"series\"][number];\ntype ChartDatum = ChartProps[\"data\"][number];\ntype CartesianSeries = ChartSeries & { type: \"area\" | \"bar\" | \"line\" };\ntype SpecialSeries = ChartSeries & { type: \"distribution\" | \"gauge\" | \"pie\" };\ntype ChartMargin = { bottom: number; left: number; right: number; top: number };\ntype CartesianChartComponent = ComponentType<{\n children: ReactNode;\n data: ChartProps[\"data\"];\n margin?: ChartMargin;\n}>;\n\nconst chartMargin: ChartMargin = { bottom: 0, left: 0, right: 16, top: 8 };\nconst compactLegendProps = {\n align: \"center\" as const,\n height: 24,\n iconSize: 7,\n verticalAlign: \"top\" as const,\n wrapperStyle: { fontSize: 11, lineHeight: \"14px\", paddingBottom: 6 },\n};\nconst axisTick = { fontSize: 10 };\nconst tooltipProps = {\n contentStyle: {\n background: \"var(--lt-surface)\",\n border: \"1px solid var(--lt-border)\",\n borderRadius: \"var(--lt-radius-sm)\",\n boxShadow: \"var(--lt-shadow-sm)\",\n color: \"var(--lt-surface-fg)\",\n fontSize: 12,\n },\n itemStyle: { color: \"var(--lt-surface-fg)\" },\n labelStyle: { color: \"var(--lt-muted-fg)\" },\n} as const;\n\nconst palette = [\n \"var(--lt-primary)\",\n \"var(--lt-success)\",\n \"var(--lt-info)\",\n \"var(--lt-warning)\",\n \"var(--lt-danger)\",\n \"var(--lt-muted-fg)\",\n];\n\nfunction colorAt(index: number): string {\n return palette[index % palette.length] ?? \"var(--lt-primary)\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction datumColor(datum: ChartDatum, series: ChartSeries, index: number): string {\n if (isRecord(datum)) {\n const color = coerceColor(datum.color);\n\n if (color) {\n return colorValue(color);\n }\n }\n\n return series.color ? colorValue(series.color) : colorAt(index);\n}\n\nfunction isCartesianSeries(series: ChartSeries): series is CartesianSeries {\n return series.type === \"area\" || series.type === \"bar\" || series.type === \"line\";\n}\n\nfunction isSpecialSeries(series: ChartSeries): series is SpecialSeries {\n return !isCartesianSeries(series);\n}\n\nfunction datumValue(datum: ChartDatum, key: string): number {\n return isRecord(datum) ? (numericValue(datum[key]) ?? 0) : 0;\n}\n\nfunction datumName(datum: ChartDatum, series: ChartSeries): string {\n if (series.nameKey === null || !isRecord(datum)) {\n return series.name;\n }\n\n const name = datum[series.nameKey];\n\n return typeof name === \"string\" ? name : series.name;\n}\n\nfunction cartesianChartFor(series: CartesianSeries[]): CartesianChartComponent {\n const types = new Set(series.map((item) => item.type));\n const firstSeries = series[0];\n\n if (firstSeries === undefined || types.size !== 1) {\n return ComposedChart;\n }\n\n switch (firstSeries.type) {\n case \"area\":\n return AreaChart;\n case \"bar\":\n return BarChart;\n case \"line\":\n return LineChart;\n }\n}\n\nfunction ChartFrame({\n children,\n description,\n id,\n title,\n}: {\n children: ReactNode;\n description: string | null;\n id?: string;\n title: string | null;\n}) {\n const hasHeader = title !== null || description !== null;\n\n return (\n <div\n className=\"flex flex-col gap-3 rounded-lt border border-lt-border bg-lt-surface p-4 text-lt-surface-fg shadow-lt-sm\"\n data-lattice-component={id}\n >\n {hasHeader && (\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n {title !== null && <div className=\"text-sm font-semibold leading-tight\">{title}</div>}\n {description !== null && (\n <div className=\"text-xs leading-5 text-lt-muted-fg\">{description}</div>\n )}\n </div>\n )}\n {children}\n </div>\n );\n}\n\nfunction CartesianChart({ props }: { props: ChartProps }) {\n const series = props.series.filter(isCartesianSeries);\n const RechartsChart = cartesianChartFor(series);\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n const ctx = { locale, timezone };\n const formatCategory = (value: unknown) => formatValue(value, props.categoryFormat, ctx);\n const formatValueTick = (value: unknown) => formatValue(value, props.valueFormat, ctx);\n const hasBarSeries = series.some((item) => item.type === \"bar\");\n const tooltipCursor = hasBarSeries\n ? { fill: \"var(--lt-muted-fg)\", fillOpacity: 0.15 }\n : { stroke: \"var(--lt-muted-fg)\", strokeOpacity: 0.4 };\n\n return (\n <ResponsiveContainer width=\"100%\" height={props.height} debounce={100}>\n <RechartsChart data={props.data} margin={chartMargin}>\n {props.grid && <CartesianGrid strokeDasharray=\"3 3\" stroke=\"var(--lt-border)\" />}\n {props.xAxis && props.categoryKey !== null && (\n <XAxis\n dataKey={props.categoryKey}\n stroke=\"var(--lt-muted-fg)\"\n tick={axisTick}\n tickFormatter={formatCategory}\n tickLine={false}\n />\n )}\n {props.yAxis && (\n <YAxis\n stroke=\"var(--lt-muted-fg)\"\n tick={axisTick}\n tickFormatter={formatValueTick}\n tickLine={false}\n width={42}\n />\n )}\n {props.tooltip && (\n <Tooltip\n {...tooltipProps}\n cursor={tooltipCursor}\n formatter={formatValueTick}\n labelFormatter={formatCategory}\n />\n )}\n {props.legend && <Legend {...compactLegendProps} />}\n {series.map((item, index) => {\n const color = item.color ? colorValue(item.color) : colorAt(index);\n const key = `${item.type}:${item.dataKey}`;\n\n if (item.type === \"area\") {\n return (\n <Area\n key={key}\n dataKey={item.dataKey}\n fill={color}\n fillOpacity={0.16}\n name={item.name}\n stackId={item.stackId ?? undefined}\n stroke={color}\n type=\"monotone\"\n />\n );\n }\n\n if (item.type === \"bar\") {\n return (\n <Bar\n key={key}\n dataKey={item.dataKey}\n fill={color}\n name={item.name}\n radius={[4, 4, 0, 0]}\n stackId={item.stackId ?? undefined}\n />\n );\n }\n\n return (\n <Line\n key={key}\n dataKey={item.dataKey}\n dot={false}\n name={item.name}\n stroke={color}\n strokeWidth={2}\n type=\"monotone\"\n />\n );\n })}\n </RechartsChart>\n </ResponsiveContainer>\n );\n}\n\nfunction PieChartView({ props, series }: { props: ChartProps; series: ChartSeries }) {\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n const ctx = { locale, timezone };\n\n return (\n <ResponsiveContainer width=\"100%\" height={props.height} debounce={100}>\n <PieChart margin={chartMargin}>\n {props.tooltip && (\n <Tooltip\n {...tooltipProps}\n formatter={(value) => formatValue(value, props.valueFormat, ctx)}\n labelFormatter={(value) => formatValue(value, props.categoryFormat, ctx)}\n />\n )}\n {props.legend && <Legend {...compactLegendProps} />}\n <Pie\n data={props.data}\n dataKey={series.dataKey}\n name={series.name}\n nameKey={series.nameKey ?? undefined}\n innerRadius={series.innerRadius}\n outerRadius=\"68%\"\n >\n {props.data.map((datum, index) => (\n <Cell key={index} fill={datumColor(datum, series, index)} />\n ))}\n </Pie>\n </PieChart>\n </ResponsiveContainer>\n );\n}\n\nfunction ChartLegend({\n entries,\n}: {\n entries: Array<{ color: string; label: string; value?: string }>;\n}) {\n return (\n <div className=\"flex flex-wrap items-center justify-center gap-x-3 gap-y-1\">\n {entries.map((entry, index) => (\n <span\n key={index}\n className=\"flex items-center gap-1 text-[11px] leading-[14px] text-lt-muted-fg\"\n >\n <span\n aria-hidden\n className=\"size-[7px] rounded-full\"\n style={{ background: entry.color }}\n />\n {entry.label}\n {entry.value !== undefined && (\n <span className=\"font-medium text-lt-surface-fg\">{entry.value}</span>\n )}\n </span>\n ))}\n </div>\n );\n}\n\nfunction GaugeChartView({ props, series }: { props: ChartProps; series: ChartSeries }) {\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n const ctx = { locale, timezone };\n const values = props.data.map((datum) => datumValue(datum, series.dataKey));\n const max = series.maxValue ?? Math.max(0, ...values);\n const legendEntries = props.data.map((datum, index) => ({\n color: datumColor(datum, series, index),\n label: datumName(datum, series),\n }));\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n {props.legend && <ChartLegend entries={legendEntries} />}\n <div className=\"relative\">\n <ResponsiveContainer width=\"100%\" height={props.height} debounce={100}>\n <RadialBarChart\n data={props.data}\n endAngle={-30}\n innerRadius={series.innerRadius}\n margin={chartMargin}\n outerRadius=\"100%\"\n startAngle={210}\n >\n <PolarAngleAxis type=\"number\" domain={[0, max]} tick={false} />\n {props.tooltip && (\n <Tooltip\n {...tooltipProps}\n formatter={(value) => formatValue(value, props.valueFormat, ctx)}\n />\n )}\n <RadialBar\n background={{ fill: \"var(--lt-muted)\" }}\n cornerRadius={6}\n dataKey={series.dataKey}\n name={series.name}\n >\n {props.data.map((datum, index) => (\n <Cell key={index} fill={datumColor(datum, series, index)} />\n ))}\n </RadialBar>\n </RadialBarChart>\n </ResponsiveContainer>\n {values.length === 1 && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <span className=\"text-2xl font-semibold text-lt-surface-fg\">\n {formatValue(values[0], props.valueFormat, ctx)}\n </span>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction DistributionChartView({ props, series }: { props: ChartProps; series: ChartSeries }) {\n const { locale } = useLocale();\n const { timezone } = useTimezone();\n const ctx = { locale, timezone };\n const segments = props.data\n .map((datum, index) => ({\n color: datumColor(datum, series, index),\n label: datumName(datum, series),\n value: datumValue(datum, series.dataKey),\n }))\n .filter((segment) => segment.value > 0);\n const total = segments.reduce((sum, segment) => sum + segment.value, 0);\n\n if (total <= 0) {\n return <div className=\"h-2.5 w-full rounded-full bg-lt-muted\" data-lattice-distribution=\"\" />;\n }\n\n const formatPercent = new Intl.NumberFormat(locale, {\n maximumFractionDigits: 1,\n style: \"percent\",\n });\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n <div\n className=\"flex h-2.5 w-full gap-0.5 overflow-hidden rounded-full\"\n data-lattice-distribution=\"\"\n >\n {segments.map((segment, index) => (\n <div\n key={index}\n style={{ background: segment.color, width: `${(segment.value / total) * 100}%` }}\n title={\n props.tooltip\n ? `${segment.label}: ${formatValue(segment.value, props.valueFormat, ctx)}`\n : undefined\n }\n />\n ))}\n </div>\n {props.legend && (\n <ChartLegend\n entries={segments.map((segment) => ({\n color: segment.color,\n label: segment.label,\n value: formatPercent.format(segment.value / total),\n }))}\n />\n )}\n </div>\n );\n}\n\nfunction SpecialChart({ props, series }: { props: ChartProps; series: SpecialSeries }) {\n switch (series.type) {\n case \"distribution\":\n return <DistributionChartView props={props} series={series} />;\n case \"gauge\":\n return <GaugeChartView props={props} series={series} />;\n case \"pie\":\n return <PieChartView props={props} series={series} />;\n }\n}\n\nconst ChartView: RendererComponent<\"chart\"> = ({ node }) => {\n const props = node.props;\n const specialSeries = props.series.find(isSpecialSeries);\n const hasCartesianSeries = props.series.some(isCartesianSeries);\n\n return (\n <ChartFrame description={props.description} id={nodeIdentity(node)} title={props.title}>\n <div className=\"min-h-0 w-full\">\n {specialSeries !== undefined && !hasCartesianSeries ? (\n <SpecialChart props={props} series={specialSeries} />\n ) : (\n <CartesianChart props={props} />\n )}\n </div>\n </ChartFrame>\n );\n};\n\nexport default ChartView;\n"],"mappings":"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"}
|
|
@@ -35,6 +35,6 @@ export declare function ActionTrigger({ action, children, }: {
|
|
|
35
35
|
export declare function useClickBehavior(props: {
|
|
36
36
|
href?: string | null;
|
|
37
37
|
method?: Method | null;
|
|
38
|
-
action?: Node | null;
|
|
38
|
+
action?: Node<"action"> | null;
|
|
39
39
|
effects?: Effect[] | null;
|
|
40
40
|
}): ClickBehavior;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"click-behavior.js","names":[],"sources":["../../resources/js/ui/click-behavior.tsx"],"sourcesContent":["import type { Method } from \"@inertiajs/core\";\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport { getActionEffects } from \"@lattice-php/lattice/effects/dispatch\";\nimport { useEffectDispatcher } from \"@lattice-php/lattice/effects/use-effect-dispatcher\";\nimport type { Effect } from \"@lattice-php/lattice/types/generated\";\n\nexport type ClickBehavior =\n | { kind: \"navigate\"; href: string; method: Method }\n | { kind: \"action\"; action: Node<\"action\"> }\n | { kind: \"effects\"; onClick: () => void }\n | { kind: \"none\" };\n\nexport type TriggerState = { onClick: () => void; processing: boolean };\n\nexport type ActionTriggerRenderer = (props: {\n action: Node<\"action\">;\n children: (trigger: TriggerState) => ReactNode;\n}) => ReactNode;\n\nconst ActionTriggerContext = createContext<ActionTriggerRenderer | null>(null);\n\nexport function ActionTriggerProvider({\n children,\n render,\n}: {\n children: ReactNode;\n render: ActionTriggerRenderer;\n}) {\n return <ActionTriggerContext.Provider value={render}>{children}</ActionTriggerContext.Provider>;\n}\n\nexport function useActionTrigger(): ActionTriggerRenderer | null {\n return useContext(ActionTriggerContext);\n}\n\nexport function ActionTrigger({\n action,\n children,\n}: {\n action: Node<\"action\">;\n children: (trigger: TriggerState) => ReactNode;\n}) {\n const render = useActionTrigger();\n\n if (!render) {\n throw new Error(\"Action triggers require an ActionTriggerProvider.\");\n }\n\n return <>{render({ action, children })}</>;\n}\n\nexport function useClickBehavior(props: {\n href?: string | null;\n method?: Method | null;\n action?: Node | null;\n effects?: Effect[] | null;\n}): ClickBehavior {\n const dispatch = useEffectDispatcher();\n const action =
|
|
1
|
+
{"version":3,"file":"click-behavior.js","names":[],"sources":["../../resources/js/ui/click-behavior.tsx"],"sourcesContent":["import type { Method } from \"@inertiajs/core\";\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport { getActionEffects } from \"@lattice-php/lattice/effects/dispatch\";\nimport { useEffectDispatcher } from \"@lattice-php/lattice/effects/use-effect-dispatcher\";\nimport type { Effect } from \"@lattice-php/lattice/types/generated\";\n\nexport type ClickBehavior =\n | { kind: \"navigate\"; href: string; method: Method }\n | { kind: \"action\"; action: Node<\"action\"> }\n | { kind: \"effects\"; onClick: () => void }\n | { kind: \"none\" };\n\nexport type TriggerState = { onClick: () => void; processing: boolean };\n\nexport type ActionTriggerRenderer = (props: {\n action: Node<\"action\">;\n children: (trigger: TriggerState) => ReactNode;\n}) => ReactNode;\n\nconst ActionTriggerContext = createContext<ActionTriggerRenderer | null>(null);\n\nexport function ActionTriggerProvider({\n children,\n render,\n}: {\n children: ReactNode;\n render: ActionTriggerRenderer;\n}) {\n return <ActionTriggerContext.Provider value={render}>{children}</ActionTriggerContext.Provider>;\n}\n\nexport function useActionTrigger(): ActionTriggerRenderer | null {\n return useContext(ActionTriggerContext);\n}\n\nexport function ActionTrigger({\n action,\n children,\n}: {\n action: Node<\"action\">;\n children: (trigger: TriggerState) => ReactNode;\n}) {\n const render = useActionTrigger();\n\n if (!render) {\n throw new Error(\"Action triggers require an ActionTriggerProvider.\");\n }\n\n return <>{render({ action, children })}</>;\n}\n\nexport function useClickBehavior(props: {\n href?: string | null;\n method?: Method | null;\n action?: Node<\"action\"> | null;\n effects?: Effect[] | null;\n}): ClickBehavior {\n const dispatch = useEffectDispatcher();\n const action = props.action ?? null;\n const effects = props.effects ?? [];\n\n if (action) {\n return { kind: \"action\", action };\n }\n\n if (effects.length > 0) {\n return { kind: \"effects\", onClick: () => dispatch(getActionEffects(effects)) };\n }\n\n if (props.href != null && props.href !== \"\") {\n return { kind: \"navigate\", href: props.href, method: props.method ?? \"get\" };\n }\n\n return { kind: \"none\" };\n}\n"],"mappings":";;;;;AAoBA,IAAM,uBAAuB,cAA4C,IAAI;AAE7E,SAAgB,sBAAsB,EACpC,UACA,UAIC;CACD,OAAO,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAS;CAAwC,CAAA;AAChG;AAEA,SAAgB,mBAAiD;CAC/D,OAAO,WAAW,oBAAoB;AACxC;AAEA,SAAgB,cAAc,EAC5B,QACA,YAIC;CACD,MAAM,SAAS,iBAAiB;CAEhC,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,mDAAmD;CAGrE,OAAO,oBAAA,YAAA,EAAA,UAAG,OAAO;EAAE;EAAQ;CAAS,CAAC,EAAI,CAAA;AAC3C;AAEA,SAAgB,iBAAiB,OAKf;CAChB,MAAM,WAAW,oBAAoB;CACrC,MAAM,SAAS,MAAM,UAAU;CAC/B,MAAM,UAAU,MAAM,WAAW,CAAC;CAElC,IAAI,QACF,OAAO;EAAE,MAAM;EAAU;CAAO;CAGlC,IAAI,QAAQ,SAAS,GACnB,OAAO;EAAE,MAAM;EAAW,eAAe,SAAS,iBAAiB,OAAO,CAAC;CAAE;CAG/E,IAAI,MAAM,QAAQ,QAAQ,MAAM,SAAS,IACvC,OAAO;EAAE,MAAM;EAAY,MAAM,MAAM;EAAM,QAAQ,MAAM,UAAU;CAAM;CAG7E,OAAO,EAAE,MAAM,OAAO;AACxB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function normalizeHex(input: string): string | null;
|
|
2
|
+
export declare function ColorPicker({ value, onChange, palette, hexLabel, paletteLabel, }: {
|
|
3
|
+
value: string;
|
|
4
|
+
onChange: (hex: string) => void;
|
|
5
|
+
palette: string[];
|
|
6
|
+
hexLabel?: string;
|
|
7
|
+
paletteLabel?: string;
|
|
8
|
+
}): import("react").JSX.Element;
|