@lattice-php/lattice 0.25.0 → 0.26.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/action/components/action-form.js +1 -1
- package/dist/action/components/action-form.js.map +1 -1
- package/dist/action/components/action-group.js +1 -1
- package/dist/action/components/action-group.js.map +1 -1
- package/dist/action/components/action.js +3 -2
- package/dist/action/components/action.js.map +1 -1
- package/dist/action/hooks/use-action.js +2 -1
- package/dist/action/hooks/use-action.js.map +1 -1
- package/dist/appearance/index.d.ts +1 -1
- package/dist/appearance/index.js +8 -8
- package/dist/appearance/index.js.map +1 -1
- package/dist/chat/components/prompt-input.js +1 -2
- package/dist/chat/components/prompt-input.js.map +1 -1
- package/dist/create-app.js +2 -2
- package/dist/create-app.js.map +1 -1
- package/dist/form/components/base/submit-button.d.ts +4 -3
- package/dist/form/components/base/submit-button.js +2 -1
- package/dist/form/components/base/submit-button.js.map +1 -1
- package/dist/form/components/fields/date-picker-field.js +3 -3
- package/dist/form/components/fields/date-picker-field.js.map +1 -1
- package/dist/form/components/fields/number-input.js +1 -1
- package/dist/form/components/fields/number-input.js.map +1 -1
- package/dist/form/components/fields/rich-editor-field.js +1 -1
- package/dist/form/components/fields/rich-editor-field.js.map +1 -1
- package/dist/form/components/fields/row-action-menu.js +3 -3
- package/dist/form/components/fields/row-action-menu.js.map +1 -1
- package/dist/form/components/fields/row-actions.d.ts +1 -1
- package/dist/form/components/fields/row-actions.js +4 -4
- package/dist/form/components/fields/row-actions.js.map +1 -1
- package/dist/form/components/fields/toggle.js +1 -1
- package/dist/form/components/fields/toggle.js.map +1 -1
- package/dist/form/components/form.js +7 -3
- package/dist/form/components/form.js.map +1 -1
- package/dist/form/components/wizard.js +1 -1
- package/dist/form/components/wizard.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/lattice.css +183 -115
- package/dist/notifications/components/notification-item.js +3 -1
- package/dist/notifications/components/notification-item.js.map +1 -1
- package/dist/notifications/components/notifications.js +2 -4
- package/dist/notifications/components/notifications.js.map +1 -1
- package/dist/table/components/bulk-bar.js +2 -0
- package/dist/table/components/bulk-bar.js.map +1 -1
- package/dist/table/components/cells/badge-cell.js +3 -6
- package/dist/table/components/cells/badge-cell.js.map +1 -1
- package/dist/table/components/cells/text-cell.js +6 -9
- package/dist/table/components/cells/text-cell.js.map +1 -1
- package/dist/table/components/column-filter-control.js +2 -2
- package/dist/table/components/column-filter-control.js.map +1 -1
- package/dist/table/components/filter-bar.js +1 -1
- package/dist/table/components/filter-bar.js.map +1 -1
- package/dist/table/components/pagination.js +6 -6
- package/dist/table/components/pagination.js.map +1 -1
- package/dist/table/lib/bulk.d.ts +3 -2
- package/dist/table/lib/bulk.js +2 -1
- package/dist/table/lib/bulk.js.map +1 -1
- package/dist/toast/toast.js +3 -1
- package/dist/toast/toast.js.map +1 -1
- package/dist/toast/variant-styles.js +15 -1
- package/dist/toast/variant-styles.js.map +1 -1
- package/dist/types/generated.d.ts +14 -9
- package/dist/ui/action-menu-context.d.ts +1 -1
- package/dist/ui/action-menu-context.js +1 -1
- package/dist/ui/action-menu-context.js.map +1 -1
- package/dist/ui/affix-group.js +1 -1
- package/dist/ui/affix-group.js.map +1 -1
- package/dist/ui/badge.d.ts +4 -7
- package/dist/ui/badge.js +11 -17
- package/dist/ui/badge.js.map +1 -1
- package/dist/ui/button.d.ts +6 -5
- package/dist/ui/button.js +154 -15
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/chart-view.js +9 -7
- package/dist/ui/chart-view.js.map +1 -1
- package/dist/ui/checkbox.js +1 -1
- package/dist/ui/checkbox.js.map +1 -1
- package/dist/ui/confirm-dialog.d.ts +4 -3
- package/dist/ui/confirm-dialog.js +3 -2
- package/dist/ui/confirm-dialog.js.map +1 -1
- package/dist/ui/control.d.ts +1 -1
- package/dist/ui/control.js +1 -1
- package/dist/ui/control.js.map +1 -1
- package/dist/ui/dialog.js +1 -1
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dropdown-menu.d.ts +2 -2
- package/dist/ui/dropdown-menu.js +2 -2
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/icon-button.d.ts +3 -3
- package/dist/ui/icon-button.js +6 -6
- package/dist/ui/icon-button.js.map +1 -1
- package/dist/ui/image-preview.js +1 -1
- package/dist/ui/image-preview.js.map +1 -1
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.js +2 -2
- package/dist/ui/info-tooltip.js +1 -1
- package/dist/ui/info-tooltip.js.map +1 -1
- package/dist/ui/input-otp.js +1 -1
- package/dist/ui/input-otp.js.map +1 -1
- package/dist/ui/label.js +1 -1
- package/dist/ui/label.js.map +1 -1
- package/dist/ui/password-input.js +1 -1
- package/dist/ui/password-input.js.map +1 -1
- package/dist/ui/progress.js +2 -2
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/text.js +1 -1
- package/dist/ui/tooltip.js +1 -1
- package/dist/ui/tooltip.js.map +1 -1
- package/dist-standalone/chunks/{chart-view-DEwGTt9d.js → chart-view-8xEKTUJV.js} +1 -1
- package/dist-standalone/chunks/{date-picker-field-CCQ9nWx0.js → date-picker-field-cdhxtVSG.js} +1 -1
- package/dist-standalone/chunks/{rich-editor-field-B9Nv1qia.js → rich-editor-field-47ov3Bny.js} +1 -1
- package/dist-standalone/lattice.css +1 -1
- package/dist-standalone/lattice.js +6 -6
- package/dist-standalone/manifest.json +5 -5
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/text-cell.tsx"],"sourcesContent":["import { DateTime } from \"@lattice-php/lattice/i18n\";\nimport {
|
|
1
|
+
{"version":3,"file":"text-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/text-cell.tsx"],"sourcesContent":["import { DateTime } from \"@lattice-php/lattice/i18n\";\nimport { Badge } from \"@lattice-php/lattice/ui/badge\";\nimport type { ReactNode } from \"react\";\nimport { formatCell, resolveLink } from \"@lattice-php/lattice/table/lib/format\";\nimport type { ColumnCellArgs, ColumnCellComponent } from \"@lattice-php/lattice/table/registry\";\nimport type { ColumnPropsOf } from \"@lattice-php/lattice/table/types\";\nimport { CopyableCell } from \"./copyable-cell\";\n\ntype TextProps = ColumnCellArgs<\"column.text\">[\"props\"];\n\nexport const TextCell: ColumnCellComponent<\"column.text\"> = (args) => {\n if (args.props.multiple) {\n return <MultipleCell {...args} />;\n }\n\n if (args.props.badge) {\n return <SingleBadgeCell {...args} />;\n }\n\n return <PlainTextCell {...args} />;\n};\n\nfunction TextBadge({ label, color }: { label: string; color?: string | null }): ReactNode {\n if (label === \"\") {\n return null;\n }\n\n return <Badge color={color}>{label}</Badge>;\n}\n\nfunction MultipleCell({ column, props, value }: ColumnCellArgs<\"column.text\">): ReactNode {\n const items = Array.isArray(value) ? value : [];\n\n if (items.length === 0) {\n return null;\n }\n\n if (!props.badge) {\n return <span>{items.map((item) => formatCell(item, column)).join(\", \")}</span>;\n }\n\n return (\n <div className=\"flex flex-wrap gap-1\">\n {items.map((item, index) => {\n const chip = item as { value: unknown; color?: string };\n\n return <TextBadge key={index} label={formatCell(chip.value, column)} color={chip.color} />;\n })}\n </div>\n );\n}\n\nfunction SingleBadgeCell({ column, props, row, value }: ColumnCellArgs<\"column.text\">): ReactNode {\n const colorKey = (props.badge as NonNullable<TextProps[\"badge\"]>).colorKey;\n\n return <TextBadge label={formatCell(value, column)} color={String(row[colorKey] ?? \"\")} />;\n}\n\nfunction PlainTextCell({ column, props, row, value }: ColumnCellArgs<\"column.text\">): ReactNode {\n const dateProps = (column.props as ColumnPropsOf<\"column.text\">).date;\n const href = resolveLink(column, row, value);\n const text = formatCell(value, column);\n\n const content = href ? (\n <a\n className=\"underline underline-offset-2\"\n href={href}\n rel={props.link?.external ? \"noreferrer\" : undefined}\n target={props.link?.external ? \"_blank\" : undefined}\n >\n {text}\n </a>\n ) : (\n text\n );\n\n if (dateProps && !href && !props.copyable && value !== null && value !== undefined) {\n return (\n <DateTime value={value} dateStyle={dateProps.dateStyle} timeStyle={dateProps.timeStyle} />\n );\n }\n\n return (\n <CopyableCell column={column} copyable={props.copyable} value={text}>\n {content}\n </CopyableCell>\n );\n}\n"],"mappings":";;;;;;AAUA,IAAa,YAAgD,SAAS;CACpE,IAAI,KAAK,MAAM,UACb,OAAO,oBAAC,cAAD,EAAc,GAAI,KAAO,CAAA;CAGlC,IAAI,KAAK,MAAM,OACb,OAAO,oBAAC,iBAAD,EAAiB,GAAI,KAAO,CAAA;CAGrC,OAAO,oBAAC,eAAD,EAAe,GAAI,KAAO,CAAA;AACnC;AAEA,SAAS,UAAU,EAAE,OAAO,SAA8D;CACxF,IAAI,UAAU,IACZ,OAAO;CAGT,OAAO,oBAAC,OAAD;EAAc;YAAQ;CAAa,CAAA;AAC5C;AAEA,SAAS,aAAa,EAAE,QAAQ,OAAO,SAAmD;CACxF,MAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;CAE9C,IAAI,MAAM,WAAW,GACnB,OAAO;CAGT,IAAI,CAAC,MAAM,OACT,OAAO,oBAAC,QAAD,EAAA,UAAO,MAAM,KAAK,SAAS,WAAW,MAAM,MAAM,CAAC,EAAE,KAAK,IAAI,EAAQ,CAAA;CAG/E,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,MAAM,KAAK,MAAM,UAAU;GAC1B,MAAM,OAAO;GAEb,OAAO,oBAAC,WAAD;IAAuB,OAAO,WAAW,KAAK,OAAO,MAAM;IAAG,OAAO,KAAK;GAAQ,GAAlE,KAAkE;EAC3F,CAAC;CACE,CAAA;AAET;AAEA,SAAS,gBAAgB,EAAE,QAAQ,OAAO,KAAK,SAAmD;CAChG,MAAM,WAAY,MAAM,MAA0C;CAElE,OAAO,oBAAC,WAAD;EAAW,OAAO,WAAW,OAAO,MAAM;EAAG,OAAO,OAAO,IAAI,aAAa,EAAE;CAAI,CAAA;AAC3F;AAEA,SAAS,cAAc,EAAE,QAAQ,OAAO,KAAK,SAAmD;CAC9F,MAAM,YAAa,OAAO,MAAuC;CACjE,MAAM,OAAO,YAAY,QAAQ,KAAK,KAAK;CAC3C,MAAM,OAAO,WAAW,OAAO,MAAM;CAErC,MAAM,UAAU,OACd,oBAAC,KAAD;EACE,WAAU;EACJ;EACN,KAAK,MAAM,MAAM,WAAW,eAAe,KAAA;EAC3C,QAAQ,MAAM,MAAM,WAAW,WAAW,KAAA;YAEzC;CACA,CAAA,IAEH;CAGF,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,YAAY,UAAU,QAAQ,UAAU,KAAA,GACvE,OACE,oBAAC,UAAD;EAAiB;EAAO,WAAW,UAAU;EAAW,WAAW,UAAU;CAAY,CAAA;CAI7F,OACE,oBAAC,cAAD;EAAsB;EAAQ,UAAU,MAAM;EAAU,OAAO;YAC5D;CACW,CAAA;AAElB"}
|
|
@@ -59,7 +59,7 @@ function ColumnFilterControl({ column, clauses, processing, onAdd, onUpdate, onR
|
|
|
59
59
|
}), /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
60
60
|
asChild: true,
|
|
61
61
|
children: /* @__PURE__ */ jsx(IconButton, {
|
|
62
|
-
|
|
62
|
+
emphasis: "segmented",
|
|
63
63
|
size: "md",
|
|
64
64
|
icon: "filter",
|
|
65
65
|
label: t("table.filter.column-filters", "{{label}} filters", { label }),
|
|
@@ -261,7 +261,7 @@ function FilterClauseRow({ column, type, operators, clause, processing, onOperat
|
|
|
261
261
|
className: "flex-1 text-sm font-medium",
|
|
262
262
|
children: operatorLabel(clause.operator)
|
|
263
263
|
}), /* @__PURE__ */ jsx(Button, {
|
|
264
|
-
|
|
264
|
+
emphasis: "outline",
|
|
265
265
|
size: "icon",
|
|
266
266
|
icon: "trash-2",
|
|
267
267
|
"aria-label": t("table.filter.remove", "Remove {{label}} filter", { label }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-filter-control.js","names":[],"sources":["../../../resources/js/table/components/column-filter-control.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Button } from \"@lattice-php/lattice/ui/button\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { NativeSelect } from \"@lattice-php/lattice/ui/native-select\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@lattice-php/lattice/ui/popover\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type {\n ColumnFilterOption,\n FilterType,\n Option,\n Op,\n} from \"@lattice-php/lattice/types/generated\";\nimport { filterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport { operatorLabel, VALUELESS_FILTER_OPERATORS } from \"@lattice-php/lattice/table/lib/query\";\nimport type { FilterClause, FilterNode, TableColumn } from \"@lattice-php/lattice/table/types\";\nimport { TableFilterControl } from \"./filter-controls\";\nimport { FilterValueInput } from \"./filter-value-input\";\n\ntype ColumnClause = { clause: FilterClause; index: number };\n\nexport function ColumnFilterControl({\n column,\n clauses,\n processing,\n onAdd,\n onUpdate,\n onRemove,\n onReplace,\n onSearch,\n}: {\n column: TableColumn;\n clauses: ColumnClause[];\n processing: boolean;\n onAdd: (clause: FilterClause) => void;\n onUpdate: (index: number, clause: FilterClause) => void;\n onRemove: (index: number) => void;\n onReplace: (field: string, clauses: FilterClause[]) => void;\n onSearch?: (query: string, signal?: AbortSignal) => Promise<Option[]>;\n}) {\n const { t } = useT(\"lattice\");\n const { filter, label: rawLabel } = column.props;\n const label = rawLabel ?? column.key;\n\n if (!filter) {\n return null;\n }\n\n if (filter.control === \"filter.select\") {\n return (\n <ColumnSelectFilter\n column={column}\n clauses={clauses}\n processing={processing}\n onReplace={onReplace}\n onSearch={onSearch}\n />\n );\n }\n\n const type = filter.type ?? \"text\";\n const operators = filter.operators ?? [];\n const defaultOperator = filter.defaultOperator ?? operators[0] ?? \"eq\";\n const primary = clauses.find((entry) => entry.clause.operator === defaultOperator) ?? clauses[0];\n\n function commitPrimary(value: string): void {\n if (value === \"\") {\n if (primary) {\n onRemove(primary.index);\n }\n\n return;\n }\n\n if (primary) {\n onUpdate(primary.index, { ...primary.clause, value });\n } else {\n onAdd({ field: column.key, operator: defaultOperator, value });\n }\n }\n\n return (\n <div className=\"flex min-w-0 max-w-80 items-stretch\">\n <div className=\"min-w-0 flex-1\">\n <FilterValueInput\n type={type}\n label={label}\n value={primary?.clause.value ?? \"\"}\n processing={processing}\n withSearchIcon={type === \"text\" || type === \"number\"}\n grouped\n testId={`filter-${column.key}-value`}\n onCommit={commitPrimary}\n onClear={primary ? () => onRemove(primary.index) : undefined}\n />\n </div>\n <Popover>\n <PopoverTrigger asChild>\n <IconButton\n variant=\"segmented\"\n size=\"md\"\n icon=\"filter\"\n label={t(\"table.filter.column-filters\", \"{{label}} filters\", { label })}\n data-test={`filter-${column.key}`}\n disabled={processing}\n >\n {clauses.length > 0 && (\n <span className=\"absolute -right-1.5 -top-1.5 inline-flex size-4 items-center justify-center rounded-full bg-lt-primary text-xs font-medium text-lt-primary-fg\">\n {clauses.length}\n </span>\n )}\n </IconButton>\n </PopoverTrigger>\n\n <PopoverContent align=\"start\" className=\"w-80 p-4\">\n <FilterClauseList\n column={column}\n clauses={clauses}\n operators={operators}\n defaultOperator={defaultOperator}\n processing={processing}\n onAdd={onAdd}\n onUpdate={onUpdate}\n onRemove={onRemove}\n />\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n\nfunction serializeColumnValue(value: unknown): string {\n if (Array.isArray(value)) {\n return value.join(\",\");\n }\n\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction ColumnSelectFilter({\n column,\n clauses,\n processing,\n onReplace,\n onSearch,\n}: {\n column: TableColumn;\n clauses: ColumnClause[];\n processing: boolean;\n onReplace: (field: string, clauses: FilterClause[]) => void;\n onSearch?: (query: string, signal?: AbortSignal) => Promise<Option[]>;\n}) {\n const { filter, label } = column.props;\n\n if (!filter) {\n return null;\n }\n\n const multiple = filter.multiple;\n const operator = filter.defaultOperator;\n const clauseOptions = filter.clauseOptions ?? [];\n const activeClauseOption = findActiveClauseOption(\n clauses.map((entry) => entry.clause),\n clauseOptions,\n );\n const active = clauses.find((entry) => entry.clause.operator === operator) ?? clauses[0];\n const value: unknown = activeClauseOption\n ? activeClauseOption.value\n : multiple\n ? active?.clause.value\n ? active.clause.value.split(\",\")\n : []\n : (active?.clause.value ?? \"\");\n\n const data: FilterNode<\"filter.select\"> = {\n key: column.key,\n type: \"filter.select\",\n props: {\n label,\n options: filter.options,\n multiple,\n searchable: filter.searchable,\n placeholder: null,\n },\n schema: [\n {\n type: \"field.select\",\n key: column.key,\n props: {\n name: \"value\",\n label,\n options: filter.options,\n multiple,\n searchable: filter.searchable,\n placeholder: null,\n },\n },\n ],\n };\n\n function change(next: unknown): void {\n const serialized = serializeColumnValue(filterValue(next).value);\n\n if (serialized === \"\") {\n onReplace(column.key, []);\n\n return;\n }\n\n const clauseOption = clauseOptions.find((option) => option.value === serialized);\n\n if (clauseOption) {\n onReplace(column.key, clausesForOption(column.key, clauseOption));\n\n return;\n }\n\n onReplace(column.key, [{ field: column.key, operator, value: serialized }]);\n }\n\n return (\n <TableFilterControl\n filter={data}\n value={{ value }}\n processing={processing}\n bare\n onChange={change}\n onSearch={onSearch ? (_field, query, signal) => onSearch(query, signal) : undefined}\n />\n );\n}\n\nfunction clausesForOption(field: string, option: ColumnFilterOption): FilterClause[] {\n return option.clauses.map((clause) => ({\n field,\n operator: clause.operator,\n value: clause.value,\n }));\n}\n\nfunction findActiveClauseOption(\n clauses: FilterClause[],\n options: ColumnFilterOption[],\n): ColumnFilterOption | undefined {\n return options.find((option) => clausesMatch(clauses, clausesForOption(\"\", option)));\n}\n\nfunction clausesMatch(active: FilterClause[], expected: FilterClause[]): boolean {\n if (active.length !== expected.length) {\n return false;\n }\n\n return expected.every((clause) =>\n active.some(\n (current) => current.operator === clause.operator && current.value === clause.value,\n ),\n );\n}\n\nfunction FilterClauseList({\n column,\n clauses,\n operators,\n defaultOperator,\n processing,\n onAdd,\n onUpdate,\n onRemove,\n}: {\n column: TableColumn;\n clauses: ColumnClause[];\n operators: Op[];\n defaultOperator: Op;\n processing: boolean;\n onAdd: (clause: FilterClause) => void;\n onUpdate: (index: number, clause: FilterClause) => void;\n onRemove: (index: number) => void;\n}) {\n const { t } = useT(\"lattice\");\n const type = column.props.filter?.type ?? \"text\";\n const [draftOperator, setDraftOperator] = useState(defaultOperator);\n const [adding, setAdding] = useState(clauses.length === 0);\n\n return (\n <div className=\"grid gap-3\">\n {clauses.map((entry) => (\n <FilterClauseRow\n key={entry.index}\n column={column}\n type={type}\n operators={operators}\n clause={entry.clause}\n processing={processing}\n onOperator={(operator) => onUpdate(entry.index, { ...entry.clause, operator })}\n onValue={(value) =>\n value === \"\" ? onRemove(entry.index) : onUpdate(entry.index, { ...entry.clause, value })\n }\n onRemove={() => onRemove(entry.index)}\n />\n ))}\n\n {adding && (\n <FilterClauseRow\n column={column}\n type={type}\n operators={operators}\n clause={{ field: column.key, operator: draftOperator, value: \"\" }}\n processing={processing}\n onOperator={(operator) => {\n if (VALUELESS_FILTER_OPERATORS.has(operator)) {\n onAdd({ field: column.key, operator, value: \"\" });\n setDraftOperator(defaultOperator);\n setAdding(false);\n return;\n }\n setDraftOperator(operator);\n }}\n onValue={(value) => {\n if (value !== \"\") {\n onAdd({ field: column.key, operator: draftOperator, value });\n setDraftOperator(defaultOperator);\n setAdding(false);\n }\n }}\n onRemove={() => setAdding(false)}\n />\n )}\n\n <div className=\"border-t border-lt-border pt-3\">\n <Button\n variant=\"secondary\"\n icon=\"plus\"\n data-test={`filter-${column.key}-add`}\n className=\"w-full\"\n disabled={processing}\n onClick={() => setAdding(true)}\n >\n {t(\"table.filter.add\", \"Add filter\")}\n </Button>\n </div>\n </div>\n );\n}\n\nfunction FilterClauseRow({\n column,\n type,\n operators,\n clause,\n processing,\n onOperator,\n onValue,\n onRemove,\n}: {\n column: TableColumn;\n type: FilterType;\n operators: Op[];\n clause: FilterClause;\n processing: boolean;\n onOperator: (operator: Op) => void;\n onValue: (value: string) => void;\n onRemove: () => void;\n}) {\n const { t } = useT(\"lattice\");\n const label = column.props.label ?? column.key;\n const valueless = VALUELESS_FILTER_OPERATORS.has(clause.operator);\n\n return (\n <div className=\"grid gap-2\">\n <div className=\"flex items-center gap-2\">\n {operators.length > 1 ? (\n <NativeSelect\n density=\"compact\"\n aria-label={t(\"table.filter.operator\", \"{{label}} operator\", { label })}\n data-test={`filter-${column.key}-operator`}\n className=\"flex-1\"\n disabled={processing}\n value={clause.operator}\n onChange={(event) => onOperator(event.target.value as Op)}\n >\n {operators.map((operator) => (\n <option key={operator} value={operator}>\n {operatorLabel(operator)}\n </option>\n ))}\n </NativeSelect>\n ) : (\n <span className=\"flex-1 text-sm font-medium\">{operatorLabel(clause.operator)}</span>\n )}\n <Button\n variant=\"outline\"\n size=\"icon\"\n icon=\"trash-2\"\n aria-label={t(\"table.filter.remove\", \"Remove {{label}} filter\", { label })}\n data-test={`filter-${column.key}-remove`}\n disabled={processing}\n onClick={onRemove}\n />\n </div>\n {!valueless && (\n <FilterValueInput\n type={type}\n label={label}\n ariaLabel={t(\"table.filter.value\", \"{{label}} filter value\", { label })}\n value={clause.value}\n processing={processing}\n onCommit={onValue}\n onClear={() => onValue(\"\")}\n />\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"column-filter-control.js","names":[],"sources":["../../../resources/js/table/components/column-filter-control.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Button } from \"@lattice-php/lattice/ui/button\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { NativeSelect } from \"@lattice-php/lattice/ui/native-select\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@lattice-php/lattice/ui/popover\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type {\n ColumnFilterOption,\n FilterType,\n Option,\n Op,\n} from \"@lattice-php/lattice/types/generated\";\nimport { filterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport { operatorLabel, VALUELESS_FILTER_OPERATORS } from \"@lattice-php/lattice/table/lib/query\";\nimport type { FilterClause, FilterNode, TableColumn } from \"@lattice-php/lattice/table/types\";\nimport { TableFilterControl } from \"./filter-controls\";\nimport { FilterValueInput } from \"./filter-value-input\";\n\ntype ColumnClause = { clause: FilterClause; index: number };\n\nexport function ColumnFilterControl({\n column,\n clauses,\n processing,\n onAdd,\n onUpdate,\n onRemove,\n onReplace,\n onSearch,\n}: {\n column: TableColumn;\n clauses: ColumnClause[];\n processing: boolean;\n onAdd: (clause: FilterClause) => void;\n onUpdate: (index: number, clause: FilterClause) => void;\n onRemove: (index: number) => void;\n onReplace: (field: string, clauses: FilterClause[]) => void;\n onSearch?: (query: string, signal?: AbortSignal) => Promise<Option[]>;\n}) {\n const { t } = useT(\"lattice\");\n const { filter, label: rawLabel } = column.props;\n const label = rawLabel ?? column.key;\n\n if (!filter) {\n return null;\n }\n\n if (filter.control === \"filter.select\") {\n return (\n <ColumnSelectFilter\n column={column}\n clauses={clauses}\n processing={processing}\n onReplace={onReplace}\n onSearch={onSearch}\n />\n );\n }\n\n const type = filter.type ?? \"text\";\n const operators = filter.operators ?? [];\n const defaultOperator = filter.defaultOperator ?? operators[0] ?? \"eq\";\n const primary = clauses.find((entry) => entry.clause.operator === defaultOperator) ?? clauses[0];\n\n function commitPrimary(value: string): void {\n if (value === \"\") {\n if (primary) {\n onRemove(primary.index);\n }\n\n return;\n }\n\n if (primary) {\n onUpdate(primary.index, { ...primary.clause, value });\n } else {\n onAdd({ field: column.key, operator: defaultOperator, value });\n }\n }\n\n return (\n <div className=\"flex min-w-0 max-w-80 items-stretch\">\n <div className=\"min-w-0 flex-1\">\n <FilterValueInput\n type={type}\n label={label}\n value={primary?.clause.value ?? \"\"}\n processing={processing}\n withSearchIcon={type === \"text\" || type === \"number\"}\n grouped\n testId={`filter-${column.key}-value`}\n onCommit={commitPrimary}\n onClear={primary ? () => onRemove(primary.index) : undefined}\n />\n </div>\n <Popover>\n <PopoverTrigger asChild>\n <IconButton\n emphasis=\"segmented\"\n size=\"md\"\n icon=\"filter\"\n label={t(\"table.filter.column-filters\", \"{{label}} filters\", { label })}\n data-test={`filter-${column.key}`}\n disabled={processing}\n >\n {clauses.length > 0 && (\n <span className=\"absolute -right-1.5 -top-1.5 inline-flex size-4 items-center justify-center rounded-full bg-lt-primary text-xs font-medium text-lt-primary-fg\">\n {clauses.length}\n </span>\n )}\n </IconButton>\n </PopoverTrigger>\n\n <PopoverContent align=\"start\" className=\"w-80 p-4\">\n <FilterClauseList\n column={column}\n clauses={clauses}\n operators={operators}\n defaultOperator={defaultOperator}\n processing={processing}\n onAdd={onAdd}\n onUpdate={onUpdate}\n onRemove={onRemove}\n />\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n\nfunction serializeColumnValue(value: unknown): string {\n if (Array.isArray(value)) {\n return value.join(\",\");\n }\n\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction ColumnSelectFilter({\n column,\n clauses,\n processing,\n onReplace,\n onSearch,\n}: {\n column: TableColumn;\n clauses: ColumnClause[];\n processing: boolean;\n onReplace: (field: string, clauses: FilterClause[]) => void;\n onSearch?: (query: string, signal?: AbortSignal) => Promise<Option[]>;\n}) {\n const { filter, label } = column.props;\n\n if (!filter) {\n return null;\n }\n\n const multiple = filter.multiple;\n const operator = filter.defaultOperator;\n const clauseOptions = filter.clauseOptions ?? [];\n const activeClauseOption = findActiveClauseOption(\n clauses.map((entry) => entry.clause),\n clauseOptions,\n );\n const active = clauses.find((entry) => entry.clause.operator === operator) ?? clauses[0];\n const value: unknown = activeClauseOption\n ? activeClauseOption.value\n : multiple\n ? active?.clause.value\n ? active.clause.value.split(\",\")\n : []\n : (active?.clause.value ?? \"\");\n\n const data: FilterNode<\"filter.select\"> = {\n key: column.key,\n type: \"filter.select\",\n props: {\n label,\n options: filter.options,\n multiple,\n searchable: filter.searchable,\n placeholder: null,\n },\n schema: [\n {\n type: \"field.select\",\n key: column.key,\n props: {\n name: \"value\",\n label,\n options: filter.options,\n multiple,\n searchable: filter.searchable,\n placeholder: null,\n },\n },\n ],\n };\n\n function change(next: unknown): void {\n const serialized = serializeColumnValue(filterValue(next).value);\n\n if (serialized === \"\") {\n onReplace(column.key, []);\n\n return;\n }\n\n const clauseOption = clauseOptions.find((option) => option.value === serialized);\n\n if (clauseOption) {\n onReplace(column.key, clausesForOption(column.key, clauseOption));\n\n return;\n }\n\n onReplace(column.key, [{ field: column.key, operator, value: serialized }]);\n }\n\n return (\n <TableFilterControl\n filter={data}\n value={{ value }}\n processing={processing}\n bare\n onChange={change}\n onSearch={onSearch ? (_field, query, signal) => onSearch(query, signal) : undefined}\n />\n );\n}\n\nfunction clausesForOption(field: string, option: ColumnFilterOption): FilterClause[] {\n return option.clauses.map((clause) => ({\n field,\n operator: clause.operator,\n value: clause.value,\n }));\n}\n\nfunction findActiveClauseOption(\n clauses: FilterClause[],\n options: ColumnFilterOption[],\n): ColumnFilterOption | undefined {\n return options.find((option) => clausesMatch(clauses, clausesForOption(\"\", option)));\n}\n\nfunction clausesMatch(active: FilterClause[], expected: FilterClause[]): boolean {\n if (active.length !== expected.length) {\n return false;\n }\n\n return expected.every((clause) =>\n active.some(\n (current) => current.operator === clause.operator && current.value === clause.value,\n ),\n );\n}\n\nfunction FilterClauseList({\n column,\n clauses,\n operators,\n defaultOperator,\n processing,\n onAdd,\n onUpdate,\n onRemove,\n}: {\n column: TableColumn;\n clauses: ColumnClause[];\n operators: Op[];\n defaultOperator: Op;\n processing: boolean;\n onAdd: (clause: FilterClause) => void;\n onUpdate: (index: number, clause: FilterClause) => void;\n onRemove: (index: number) => void;\n}) {\n const { t } = useT(\"lattice\");\n const type = column.props.filter?.type ?? \"text\";\n const [draftOperator, setDraftOperator] = useState(defaultOperator);\n const [adding, setAdding] = useState(clauses.length === 0);\n\n return (\n <div className=\"grid gap-3\">\n {clauses.map((entry) => (\n <FilterClauseRow\n key={entry.index}\n column={column}\n type={type}\n operators={operators}\n clause={entry.clause}\n processing={processing}\n onOperator={(operator) => onUpdate(entry.index, { ...entry.clause, operator })}\n onValue={(value) =>\n value === \"\" ? onRemove(entry.index) : onUpdate(entry.index, { ...entry.clause, value })\n }\n onRemove={() => onRemove(entry.index)}\n />\n ))}\n\n {adding && (\n <FilterClauseRow\n column={column}\n type={type}\n operators={operators}\n clause={{ field: column.key, operator: draftOperator, value: \"\" }}\n processing={processing}\n onOperator={(operator) => {\n if (VALUELESS_FILTER_OPERATORS.has(operator)) {\n onAdd({ field: column.key, operator, value: \"\" });\n setDraftOperator(defaultOperator);\n setAdding(false);\n return;\n }\n setDraftOperator(operator);\n }}\n onValue={(value) => {\n if (value !== \"\") {\n onAdd({ field: column.key, operator: draftOperator, value });\n setDraftOperator(defaultOperator);\n setAdding(false);\n }\n }}\n onRemove={() => setAdding(false)}\n />\n )}\n\n <div className=\"border-t border-lt-border pt-3\">\n <Button\n variant=\"secondary\"\n icon=\"plus\"\n data-test={`filter-${column.key}-add`}\n className=\"w-full\"\n disabled={processing}\n onClick={() => setAdding(true)}\n >\n {t(\"table.filter.add\", \"Add filter\")}\n </Button>\n </div>\n </div>\n );\n}\n\nfunction FilterClauseRow({\n column,\n type,\n operators,\n clause,\n processing,\n onOperator,\n onValue,\n onRemove,\n}: {\n column: TableColumn;\n type: FilterType;\n operators: Op[];\n clause: FilterClause;\n processing: boolean;\n onOperator: (operator: Op) => void;\n onValue: (value: string) => void;\n onRemove: () => void;\n}) {\n const { t } = useT(\"lattice\");\n const label = column.props.label ?? column.key;\n const valueless = VALUELESS_FILTER_OPERATORS.has(clause.operator);\n\n return (\n <div className=\"grid gap-2\">\n <div className=\"flex items-center gap-2\">\n {operators.length > 1 ? (\n <NativeSelect\n density=\"compact\"\n aria-label={t(\"table.filter.operator\", \"{{label}} operator\", { label })}\n data-test={`filter-${column.key}-operator`}\n className=\"flex-1\"\n disabled={processing}\n value={clause.operator}\n onChange={(event) => onOperator(event.target.value as Op)}\n >\n {operators.map((operator) => (\n <option key={operator} value={operator}>\n {operatorLabel(operator)}\n </option>\n ))}\n </NativeSelect>\n ) : (\n <span className=\"flex-1 text-sm font-medium\">{operatorLabel(clause.operator)}</span>\n )}\n <Button\n emphasis=\"outline\"\n size=\"icon\"\n icon=\"trash-2\"\n aria-label={t(\"table.filter.remove\", \"Remove {{label}} filter\", { label })}\n data-test={`filter-${column.key}-remove`}\n disabled={processing}\n onClick={onRemove}\n />\n </div>\n {!valueless && (\n <FilterValueInput\n type={type}\n label={label}\n ariaLabel={t(\"table.filter.value\", \"{{label}} filter value\", { label })}\n value={clause.value}\n processing={processing}\n onCommit={onValue}\n onClear={() => onValue(\"\")}\n />\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -37,7 +37,7 @@ function FilterBar({ clauses, columnsByKey, indicators, processing, onRemoveClau
|
|
|
37
37
|
/* @__PURE__ */ jsx("button", {
|
|
38
38
|
type: "button",
|
|
39
39
|
"data-test": "table-filters-reset",
|
|
40
|
-
className: "text-lt-muted-fg underline-offset-2 hover:underline disabled:
|
|
40
|
+
className: "text-lt-muted-fg underline-offset-2 hover:underline disabled:text-lt-disabled-fg",
|
|
41
41
|
disabled: processing,
|
|
42
42
|
onClick: onReset,
|
|
43
43
|
children: t("table.filter.reset-all", "Reset all")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-bar.js","names":[],"sources":["../../../resources/js/table/components/filter-bar.tsx"],"sourcesContent":["import { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@lattice-php/lattice/ui/popover\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { Option } from \"@lattice-php/lattice/types/generated\";\nimport { isActiveFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport { operatorLabel, VALUELESS_FILTER_OPERATORS } from \"@lattice-php/lattice/table/lib/query\";\nimport type {\n FilterClause,\n FilterIndicator,\n FilterNode,\n TableColumn,\n} from \"@lattice-php/lattice/table/types\";\nimport { TableFilterControl } from \"./filter-controls\";\n\nexport function FilterBar({\n clauses,\n columnsByKey,\n indicators,\n processing,\n onRemoveClause,\n onChange,\n onReset,\n}: {\n clauses: FilterClause[];\n columnsByKey: Map<string, TableColumn>;\n indicators: FilterIndicator[];\n processing: boolean;\n onRemoveClause: (index: number) => void;\n onChange: (key: string, value: unknown) => void;\n onReset: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n if (clauses.length === 0 && indicators.length === 0) {\n return null;\n }\n\n return (\n <div className=\"border-b border-lt-border px-4 py-3\">\n <div className=\"flex flex-wrap items-center gap-2 text-sm\">\n {clauses.map((clause, index) => {\n const label = columnsByKey.get(clause.field)?.props.label ?? clause.field;\n const valueless = VALUELESS_FILTER_OPERATORS.has(clause.operator);\n\n return (\n <FilterChip\n key={`${clause.field}-${clause.operator}-${index}`}\n label={`${label} ${operatorLabel(clause.operator)}`}\n value={valueless ? \"\" : clause.value}\n removeTestId={`filter-chip-${clause.field}-remove`}\n removeLabel={t(\"table.filter.remove\", \"Remove {{label}} filter\", { label })}\n processing={processing}\n onRemove={() => onRemoveClause(index)}\n />\n );\n })}\n {indicators.map((indicator) => (\n <FilterChip\n key={`${indicator.filter}:${indicator.label}:${indicator.value}`}\n label={indicator.label}\n value={indicator.value}\n removeTestId={`table-filter-chip-${indicator.filter}-remove`}\n removeLabel={t(\"table.filter.remove\", \"Remove {{label}} filter\", {\n label: indicator.label,\n })}\n processing={processing}\n onRemove={() => onChange(indicator.filter, undefined)}\n />\n ))}\n <button\n type=\"button\"\n data-test=\"table-filters-reset\"\n className=\"text-lt-muted-fg underline-offset-2 hover:underline disabled:
|
|
1
|
+
{"version":3,"file":"filter-bar.js","names":[],"sources":["../../../resources/js/table/components/filter-bar.tsx"],"sourcesContent":["import { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@lattice-php/lattice/ui/popover\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { Option } from \"@lattice-php/lattice/types/generated\";\nimport { isActiveFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport { operatorLabel, VALUELESS_FILTER_OPERATORS } from \"@lattice-php/lattice/table/lib/query\";\nimport type {\n FilterClause,\n FilterIndicator,\n FilterNode,\n TableColumn,\n} from \"@lattice-php/lattice/table/types\";\nimport { TableFilterControl } from \"./filter-controls\";\n\nexport function FilterBar({\n clauses,\n columnsByKey,\n indicators,\n processing,\n onRemoveClause,\n onChange,\n onReset,\n}: {\n clauses: FilterClause[];\n columnsByKey: Map<string, TableColumn>;\n indicators: FilterIndicator[];\n processing: boolean;\n onRemoveClause: (index: number) => void;\n onChange: (key: string, value: unknown) => void;\n onReset: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n if (clauses.length === 0 && indicators.length === 0) {\n return null;\n }\n\n return (\n <div className=\"border-b border-lt-border px-4 py-3\">\n <div className=\"flex flex-wrap items-center gap-2 text-sm\">\n {clauses.map((clause, index) => {\n const label = columnsByKey.get(clause.field)?.props.label ?? clause.field;\n const valueless = VALUELESS_FILTER_OPERATORS.has(clause.operator);\n\n return (\n <FilterChip\n key={`${clause.field}-${clause.operator}-${index}`}\n label={`${label} ${operatorLabel(clause.operator)}`}\n value={valueless ? \"\" : clause.value}\n removeTestId={`filter-chip-${clause.field}-remove`}\n removeLabel={t(\"table.filter.remove\", \"Remove {{label}} filter\", { label })}\n processing={processing}\n onRemove={() => onRemoveClause(index)}\n />\n );\n })}\n {indicators.map((indicator) => (\n <FilterChip\n key={`${indicator.filter}:${indicator.label}:${indicator.value}`}\n label={indicator.label}\n value={indicator.value}\n removeTestId={`table-filter-chip-${indicator.filter}-remove`}\n removeLabel={t(\"table.filter.remove\", \"Remove {{label}} filter\", {\n label: indicator.label,\n })}\n processing={processing}\n onRemove={() => onChange(indicator.filter, undefined)}\n />\n ))}\n <button\n type=\"button\"\n data-test=\"table-filters-reset\"\n className=\"text-lt-muted-fg underline-offset-2 hover:underline disabled:text-lt-disabled-fg\"\n disabled={processing}\n onClick={onReset}\n >\n {t(\"table.filter.reset-all\", \"Reset all\")}\n </button>\n </div>\n </div>\n );\n}\n\nfunction FilterChip({\n label,\n value,\n removeTestId,\n removeLabel,\n processing,\n onRemove,\n}: {\n label: string;\n value: string;\n removeTestId: string;\n removeLabel: string;\n processing: boolean;\n onRemove: () => void;\n}) {\n return (\n <span className=\"inline-flex items-center gap-1.5 rounded-lt-sm bg-lt-muted px-2 py-1\">\n <span>\n {value === \"\" ? (\n <span className=\"font-semibold\">{label}</span>\n ) : (\n <>\n {`${label}: `}\n <span className=\"font-semibold\">{value}</span>\n </>\n )}\n </span>\n <IconButton\n size=\"xs\"\n icon=\"x\"\n label={removeLabel}\n data-test={removeTestId}\n disabled={processing}\n onClick={onRemove}\n />\n </span>\n );\n}\n\nexport function FilterMenu({\n filters,\n values,\n processing,\n onChange,\n onSearch,\n}: {\n filters: FilterNode[];\n values: Record<string, unknown>;\n processing: boolean;\n onChange: (key: string, value: unknown) => void;\n onSearch?: (searchKey: string, query: string, signal?: AbortSignal) => Promise<Option[]>;\n}) {\n const { t } = useT(\"lattice\");\n const active = filters.filter((filter) => isActiveFilterValue(values[filter.key]));\n const filtersLabel = t(\"table.filter.filters\", \"Filters\");\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <IconButton\n size=\"sm\"\n icon=\"filter\"\n label={filtersLabel}\n data-test=\"table-filters-menu\"\n disabled={processing}\n >\n {active.length > 0 && (\n <span className=\"absolute -right-1 -top-1 inline-flex size-3.5 items-center justify-center rounded-full bg-lt-primary text-[10px] font-medium leading-none text-lt-primary-fg\">\n {active.length}\n </span>\n )}\n </IconButton>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-80 p-4\">\n <div className=\"grid gap-3\">\n {filters.map((filter) => (\n <div key={filter.key} className=\"grid gap-1\">\n <TableFilterControl\n filter={filter}\n value={values[filter.key]}\n processing={processing}\n onChange={(value) => onChange(filter.key, value)}\n onSearch={\n onSearch\n ? (field, query, signal) =>\n onSearch(`filter:${filter.key}.${field}`, query, signal)\n : undefined\n }\n />\n </div>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
|
|
|
15
15
|
ref: infiniteLoaderRef,
|
|
16
16
|
className: "flex items-center gap-2",
|
|
17
17
|
children: pagination.hasMore ? /* @__PURE__ */ jsx(Button, {
|
|
18
|
-
|
|
18
|
+
emphasis: "outline",
|
|
19
19
|
"data-test": "pagination-load-more",
|
|
20
20
|
disabled: processing,
|
|
21
21
|
onClick: onLoadMore,
|
|
@@ -27,13 +27,13 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
|
|
|
27
27
|
}) : mode === "simple" ? /* @__PURE__ */ jsxs("div", {
|
|
28
28
|
className: "flex items-center gap-2",
|
|
29
29
|
children: [/* @__PURE__ */ jsx(Button, {
|
|
30
|
-
|
|
30
|
+
emphasis: "outline",
|
|
31
31
|
"data-test": "pagination-previous",
|
|
32
32
|
disabled: processing || currentPage <= 1,
|
|
33
33
|
onClick: () => onPage(currentPage - 1),
|
|
34
34
|
children: t("table.pagination.previous", "Previous")
|
|
35
35
|
}), /* @__PURE__ */ jsx(Button, {
|
|
36
|
-
|
|
36
|
+
emphasis: "outline",
|
|
37
37
|
"data-test": "pagination-next",
|
|
38
38
|
disabled: processing || !hasNextPage,
|
|
39
39
|
onClick: () => onPage(currentPage + 1),
|
|
@@ -43,14 +43,14 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
|
|
|
43
43
|
className: "flex items-center gap-2",
|
|
44
44
|
children: [
|
|
45
45
|
/* @__PURE__ */ jsx(Button, {
|
|
46
|
-
|
|
46
|
+
emphasis: "outline",
|
|
47
47
|
"data-test": "pagination-previous",
|
|
48
48
|
disabled: processing || currentPage <= 1,
|
|
49
49
|
onClick: () => onPage(currentPage - 1),
|
|
50
50
|
children: t("table.pagination.previous", "Previous")
|
|
51
51
|
}),
|
|
52
52
|
visiblePages.map((pageNumber) => /* @__PURE__ */ jsx(Button, {
|
|
53
|
-
|
|
53
|
+
emphasis: "outline",
|
|
54
54
|
size: "icon",
|
|
55
55
|
"data-test": `pagination-page-${pageNumber}`,
|
|
56
56
|
disabled: processing || pageNumber === currentPage,
|
|
@@ -60,7 +60,7 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
|
|
|
60
60
|
children: pageNumber
|
|
61
61
|
}, pageNumber)),
|
|
62
62
|
/* @__PURE__ */ jsx(Button, {
|
|
63
|
-
|
|
63
|
+
emphasis: "outline",
|
|
64
64
|
"data-test": "pagination-next",
|
|
65
65
|
disabled: processing || !hasNextPage,
|
|
66
66
|
onClick: () => onPage(currentPage + 1),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","names":[],"sources":["../../../resources/js/table/components/pagination.tsx"],"sourcesContent":["import type { RefObject } from \"react\";\nimport { Button } from \"@lattice-php/lattice/ui/button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { PaginationType } from \"@lattice-php/lattice/types/generated\";\nimport type { TablePagination as TablePaginationData } from \"@lattice-php/lattice/table/types\";\n\nexport function TablePagination({\n pagination,\n currentPage,\n processing,\n mode,\n hasNextPage,\n visiblePages,\n infiniteLoaderRef,\n onPage,\n onLoadMore,\n}: {\n pagination: TablePaginationData;\n currentPage: number;\n processing: boolean;\n mode: PaginationType;\n hasNextPage: boolean;\n visiblePages: number[];\n infiniteLoaderRef: RefObject<HTMLDivElement | null>;\n onPage: (page: number) => void;\n onLoadMore: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n return (\n <div\n data-slot=\"table-pagination\"\n className=\"flex items-center justify-between gap-3 border-t border-lt-border p-4 text-sm\"\n >\n <span>\n {pagination.total == null\n ? t(\"table.pagination.page\", \"Page {{page}}\", { page: currentPage })\n : t(\"table.pagination.showing\", \"Showing {{from}}-{{to}} of {{total}}\", {\n from: pagination.from ?? 0,\n to: pagination.to ?? 0,\n total: pagination.total,\n })}\n </span>\n {mode === \"infinite\" ? (\n <div ref={infiniteLoaderRef} className=\"flex items-center gap-2\">\n {pagination.hasMore ? (\n <Button\n
|
|
1
|
+
{"version":3,"file":"pagination.js","names":[],"sources":["../../../resources/js/table/components/pagination.tsx"],"sourcesContent":["import type { RefObject } from \"react\";\nimport { Button } from \"@lattice-php/lattice/ui/button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { PaginationType } from \"@lattice-php/lattice/types/generated\";\nimport type { TablePagination as TablePaginationData } from \"@lattice-php/lattice/table/types\";\n\nexport function TablePagination({\n pagination,\n currentPage,\n processing,\n mode,\n hasNextPage,\n visiblePages,\n infiniteLoaderRef,\n onPage,\n onLoadMore,\n}: {\n pagination: TablePaginationData;\n currentPage: number;\n processing: boolean;\n mode: PaginationType;\n hasNextPage: boolean;\n visiblePages: number[];\n infiniteLoaderRef: RefObject<HTMLDivElement | null>;\n onPage: (page: number) => void;\n onLoadMore: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n return (\n <div\n data-slot=\"table-pagination\"\n className=\"flex items-center justify-between gap-3 border-t border-lt-border p-4 text-sm\"\n >\n <span>\n {pagination.total == null\n ? t(\"table.pagination.page\", \"Page {{page}}\", { page: currentPage })\n : t(\"table.pagination.showing\", \"Showing {{from}}-{{to}} of {{total}}\", {\n from: pagination.from ?? 0,\n to: pagination.to ?? 0,\n total: pagination.total,\n })}\n </span>\n {mode === \"infinite\" ? (\n <div ref={infiniteLoaderRef} className=\"flex items-center gap-2\">\n {pagination.hasMore ? (\n <Button\n emphasis=\"outline\"\n data-test=\"pagination-load-more\"\n disabled={processing}\n onClick={onLoadMore}\n >\n {processing\n ? t(\"table.pagination.loading\", \"Loading...\")\n : t(\"table.pagination.load-more\", \"Load more\")}\n </Button>\n ) : (\n <span className=\"text-lt-muted-fg\">\n {t(\"table.pagination.all-loaded\", \"All rows loaded\")}\n </span>\n )}\n </div>\n ) : mode === \"simple\" ? (\n <div className=\"flex items-center gap-2\">\n <Button\n emphasis=\"outline\"\n data-test=\"pagination-previous\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n {t(\"table.pagination.previous\", \"Previous\")}\n </Button>\n <Button\n emphasis=\"outline\"\n data-test=\"pagination-next\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n {t(\"table.pagination.next\", \"Next\")}\n </Button>\n </div>\n ) : mode === \"table\" ? (\n <div className=\"flex items-center gap-2\">\n <Button\n emphasis=\"outline\"\n data-test=\"pagination-previous\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n {t(\"table.pagination.previous\", \"Previous\")}\n </Button>\n {visiblePages.map((pageNumber) => (\n <Button\n key={pageNumber}\n emphasis=\"outline\"\n size=\"icon\"\n data-test={`pagination-page-${pageNumber}`}\n disabled={processing || pageNumber === currentPage}\n aria-current={pageNumber === currentPage ? \"page\" : undefined}\n aria-label={t(\"table.pagination.page\", \"Page {{page}}\", { page: pageNumber })}\n onClick={() => onPage(pageNumber)}\n >\n {pageNumber}\n </Button>\n ))}\n <Button\n emphasis=\"outline\"\n data-test=\"pagination-next\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n {t(\"table.pagination.next\", \"Next\")}\n </Button>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;AAMA,SAAgB,gBAAgB,EAC9B,YACA,aACA,YACA,MACA,aACA,cACA,mBACA,QACA,cAWC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,qBAAC,OAAD;EACE,aAAU;EACV,WAAU;YAFZ,CAIE,oBAAC,QAAD,EAAA,UACG,WAAW,SAAS,OACjB,EAAE,yBAAyB,iBAAiB,EAAE,MAAM,YAAY,CAAC,IACjE,EAAE,4BAA4B,wCAAwC;GACpE,MAAM,WAAW,QAAQ;GACzB,IAAI,WAAW,MAAM;GACrB,OAAO,WAAW;EACpB,CAAC,EACD,CAAA,GACL,SAAS,aACR,oBAAC,OAAD;GAAK,KAAK;GAAmB,WAAU;aACpC,WAAW,UACV,oBAAC,QAAD;IACE,UAAS;IACT,aAAU;IACV,UAAU;IACV,SAAS;cAER,aACG,EAAE,4BAA4B,YAAY,IAC1C,EAAE,8BAA8B,WAAW;GACzC,CAAA,IAER,oBAAC,QAAD;IAAM,WAAU;cACb,EAAE,+BAA+B,iBAAiB;GAC/C,CAAA;EAEL,CAAA,IACH,SAAS,WACX,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,QAAD;IACE,UAAS;IACT,aAAU;IACV,UAAU,cAAc,eAAe;IACvC,eAAe,OAAO,cAAc,CAAC;cAEpC,EAAE,6BAA6B,UAAU;GACpC,CAAA,GACR,oBAAC,QAAD;IACE,UAAS;IACT,aAAU;IACV,UAAU,cAAc,CAAC;IACzB,eAAe,OAAO,cAAc,CAAC;cAEpC,EAAE,yBAAyB,MAAM;GAC5B,CAAA,CACL;OACH,SAAS,UACX,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,QAAD;KACE,UAAS;KACT,aAAU;KACV,UAAU,cAAc,eAAe;KACvC,eAAe,OAAO,cAAc,CAAC;eAEpC,EAAE,6BAA6B,UAAU;IACpC,CAAA;IACP,aAAa,KAAK,eACjB,oBAAC,QAAD;KAEE,UAAS;KACT,MAAK;KACL,aAAW,mBAAmB;KAC9B,UAAU,cAAc,eAAe;KACvC,gBAAc,eAAe,cAAc,SAAS,KAAA;KACpD,cAAY,EAAE,yBAAyB,iBAAiB,EAAE,MAAM,WAAW,CAAC;KAC5E,eAAe,OAAO,UAAU;eAE/B;IACK,GAVD,UAUC,CACT;IACD,oBAAC,QAAD;KACE,UAAS;KACT,aAAU;KACV,UAAU,cAAc,CAAC;KACzB,eAAe,OAAO,cAAc,CAAC;eAEpC,EAAE,yBAAyB,MAAM;IAC5B,CAAA;GACL;OACH,IACD;;AAET"}
|
package/dist/table/lib/bulk.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Method } from '@inertiajs/core';
|
|
2
2
|
import { Node } from '../../core/types.js';
|
|
3
|
-
import { Action,
|
|
3
|
+
import { Action, Emphasis, Variant } from '../../types/generated.js';
|
|
4
4
|
import { ActionNode } from '../types.js';
|
|
5
5
|
export type BulkAction = {
|
|
6
6
|
id: string;
|
|
@@ -8,7 +8,8 @@ export type BulkAction = {
|
|
|
8
8
|
method: Method;
|
|
9
9
|
endpoint: string;
|
|
10
10
|
ref: string;
|
|
11
|
-
variant:
|
|
11
|
+
variant: Variant | null;
|
|
12
|
+
emphasis: Emphasis | null;
|
|
12
13
|
confirmation: Action["confirmation"];
|
|
13
14
|
form: Node | null;
|
|
14
15
|
modalSide: Action["modalSide"];
|
package/dist/table/lib/bulk.js
CHANGED
|
@@ -11,7 +11,8 @@ function getBulkActions(actions) {
|
|
|
11
11
|
method: props.method ?? "post",
|
|
12
12
|
endpoint: props.endpoint,
|
|
13
13
|
ref: props.ref ?? "",
|
|
14
|
-
variant: props.variant
|
|
14
|
+
variant: props.variant,
|
|
15
|
+
emphasis: props.emphasis,
|
|
15
16
|
confirmation: props.confirmation,
|
|
16
17
|
form: props.form,
|
|
17
18
|
modalSide: props.modalSide,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bulk.js","names":[],"sources":["../../../resources/js/table/lib/bulk.ts"],"sourcesContent":["import type { Method } from \"@inertiajs/core\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { Action,
|
|
1
|
+
{"version":3,"file":"bulk.js","names":[],"sources":["../../../resources/js/table/lib/bulk.ts"],"sourcesContent":["import type { Method } from \"@inertiajs/core\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { Action, Emphasis, Variant } from \"@lattice-php/lattice/types/generated\";\nimport type { ActionNode } from \"@lattice-php/lattice/table/types\";\nimport { actionLabel } from \"@lattice-php/lattice/action/lib/action-label\";\n\nexport type BulkAction = {\n id: string;\n label: string;\n method: Method;\n endpoint: string;\n ref: string;\n variant: Variant | null;\n emphasis: Emphasis | null;\n confirmation: Action[\"confirmation\"];\n form: Node | null;\n modalSide: Action[\"modalSide\"];\n modalWidth: Action[\"modalWidth\"];\n};\n\nexport function getBulkActions(actions: ActionNode[] | undefined): BulkAction[] {\n return (actions ?? []).flatMap((node): BulkAction[] => {\n if (node.type === \"action.group\") {\n return [];\n }\n\n const props = node.props;\n\n if (!props.endpoint) {\n return [];\n }\n\n return [\n {\n id: node.id ?? \"\",\n label: actionLabel(node),\n method: props.method ?? \"post\",\n endpoint: props.endpoint,\n ref: props.ref ?? \"\",\n variant: props.variant,\n emphasis: props.emphasis,\n confirmation: props.confirmation,\n form: props.form,\n modalSide: props.modalSide,\n modalWidth: props.modalWidth,\n },\n ];\n });\n}\n"],"mappings":";;AAoBA,SAAgB,eAAe,SAAiD;CAC9E,QAAQ,WAAW,CAAC,GAAG,SAAS,SAAuB;EACrD,IAAI,KAAK,SAAS,gBAChB,OAAO,CAAC;EAGV,MAAM,QAAQ,KAAK;EAEnB,IAAI,CAAC,MAAM,UACT,OAAO,CAAC;EAGV,OAAO,CACL;GACE,IAAI,KAAK,MAAM;GACf,OAAO,YAAY,IAAI;GACvB,QAAQ,MAAM,UAAU;GACxB,UAAU,MAAM;GAChB,KAAK,MAAM,OAAO;GAClB,SAAS,MAAM;GACf,UAAU,MAAM;GAChB,cAAc,MAAM;GACpB,MAAM,MAAM;GACZ,WAAW,MAAM;GACjB,YAAY,MAAM;EACpB,CACF;CACF,CAAC;AACH"}
|
package/dist/toast/toast.js
CHANGED
|
@@ -2,10 +2,12 @@ import { LATTICE_EVENT } from "../core/event-names.js";
|
|
|
2
2
|
import { isTranslatable } from "../i18n/translatable.js";
|
|
3
3
|
//#region resources/js/toast/toast.ts
|
|
4
4
|
var variants = [
|
|
5
|
+
"primary",
|
|
6
|
+
"secondary",
|
|
5
7
|
"success",
|
|
6
8
|
"info",
|
|
7
9
|
"warning",
|
|
8
|
-
"
|
|
10
|
+
"danger"
|
|
9
11
|
];
|
|
10
12
|
function isVariant(value) {
|
|
11
13
|
return variants.some((variant) => variant === value);
|
package/dist/toast/toast.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.js","names":[],"sources":["../../resources/js/toast/toast.ts"],"sourcesContent":["import type { Toast as ToastMessage, Variant } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { isTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\n\nexport type { ToastMessage, Variant };\n\nconst variants = [\"success\"
|
|
1
|
+
{"version":3,"file":"toast.js","names":[],"sources":["../../resources/js/toast/toast.ts"],"sourcesContent":["import type { Toast as ToastMessage, Variant } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { isTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\n\nexport type { ToastMessage, Variant };\n\nconst variants = [\n \"primary\",\n \"secondary\",\n \"success\",\n \"info\",\n \"warning\",\n \"danger\",\n] as const satisfies readonly Variant[];\n\nexport function isVariant(value: unknown): value is Variant {\n return variants.some((variant) => variant === value);\n}\n\nexport function normalizeToastMessage(value: unknown): ToastMessage | null {\n if (typeof value !== \"object\" || value === null) {\n return null;\n }\n\n const toast = value as Record<string, unknown>;\n\n const rawMessage = toast.message;\n const message =\n typeof rawMessage === \"string\" ? rawMessage : isTranslatable(rawMessage) ? rawMessage : null;\n\n if (message === null || message === \"\") {\n return null;\n }\n\n return {\n action: (toast.action as ToastMessage[\"action\"]) ?? null,\n dismissible: toast.dismissible !== false,\n duration: typeof toast.duration === \"number\" ? toast.duration : null,\n message,\n persistent: toast.persistent === true,\n variant: isVariant(toast.variant) ? toast.variant : \"success\",\n };\n}\n\nexport function onToast(callback: (toast: ToastMessage) => void): () => void {\n const listener = (event: Event): void => {\n const toast = normalizeToastMessage((event as CustomEvent).detail);\n\n if (toast) {\n callback(toast);\n }\n };\n\n window.addEventListener(LATTICE_EVENT.toast, listener);\n\n return () => window.removeEventListener(LATTICE_EVENT.toast, listener);\n}\n"],"mappings":";;;AAMA,IAAM,WAAW;CACf;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgB,UAAU,OAAkC;CAC1D,OAAO,SAAS,MAAM,YAAY,YAAY,KAAK;AACrD;AAEA,SAAgB,sBAAsB,OAAqC;CACzE,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAGT,MAAM,QAAQ;CAEd,MAAM,aAAa,MAAM;CACzB,MAAM,UACJ,OAAO,eAAe,WAAW,aAAa,eAAe,UAAU,IAAI,aAAa;CAE1F,IAAI,YAAY,QAAQ,YAAY,IAClC,OAAO;CAGT,OAAO;EACL,QAAS,MAAM,UAAqC;EACpD,aAAa,MAAM,gBAAgB;EACnC,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;EAChE;EACA,YAAY,MAAM,eAAe;EACjC,SAAS,UAAU,MAAM,OAAO,IAAI,MAAM,UAAU;CACtD;AACF;AAEA,SAAgB,QAAQ,UAAqD;CAC3E,MAAM,YAAY,UAAuB;EACvC,MAAM,QAAQ,sBAAuB,MAAsB,MAAM;EAEjE,IAAI,OACF,SAAS,KAAK;CAElB;CAEA,OAAO,iBAAiB,cAAc,OAAO,QAAQ;CAErD,aAAa,OAAO,oBAAoB,cAAc,OAAO,QAAQ;AACvE"}
|
|
@@ -2,6 +2,20 @@ import { Icon } from "../icons/sprite.js";
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region resources/js/toast/variant-styles.tsx
|
|
4
4
|
var variantStyles = {
|
|
5
|
+
primary: {
|
|
6
|
+
accent: "border-l-lt-primary",
|
|
7
|
+
icon: /* @__PURE__ */ jsx(Icon, {
|
|
8
|
+
name: "info",
|
|
9
|
+
className: "size-lt-icon-lg shrink-0 text-lt-primary"
|
|
10
|
+
})
|
|
11
|
+
},
|
|
12
|
+
secondary: {
|
|
13
|
+
accent: "border-l-lt-secondary",
|
|
14
|
+
icon: /* @__PURE__ */ jsx(Icon, {
|
|
15
|
+
name: "info",
|
|
16
|
+
className: "size-lt-icon-lg shrink-0 text-lt-muted-fg"
|
|
17
|
+
})
|
|
18
|
+
},
|
|
5
19
|
success: {
|
|
6
20
|
accent: "border-l-lt-success",
|
|
7
21
|
icon: /* @__PURE__ */ jsx(Icon, {
|
|
@@ -23,7 +37,7 @@ var variantStyles = {
|
|
|
23
37
|
className: "size-lt-icon-lg shrink-0 text-lt-warning"
|
|
24
38
|
})
|
|
25
39
|
},
|
|
26
|
-
|
|
40
|
+
danger: {
|
|
27
41
|
accent: "border-l-lt-danger",
|
|
28
42
|
icon: /* @__PURE__ */ jsx(Icon, {
|
|
29
43
|
name: "circle-x",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"variant-styles.js","names":[],"sources":["../../resources/js/toast/variant-styles.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport type { ReactNode } from \"react\";\nimport type { Variant } from \"@lattice-php/lattice/types/generated\";\n\nexport const variantStyles: Record<Variant, { accent: string; icon: ReactNode }> = {\n success: {\n accent: \"border-l-lt-success\",\n icon: <Icon name=\"circle-check\" className=\"size-lt-icon-lg shrink-0 text-lt-success\" />,\n },\n info: {\n accent: \"border-l-lt-info\",\n icon: <Icon name=\"info\" className=\"size-lt-icon-lg shrink-0 text-lt-info\" />,\n },\n warning: {\n accent: \"border-l-lt-warning\",\n icon: <Icon name=\"circle-alert\" className=\"size-lt-icon-lg shrink-0 text-lt-warning\" />,\n },\n
|
|
1
|
+
{"version":3,"file":"variant-styles.js","names":[],"sources":["../../resources/js/toast/variant-styles.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport type { ReactNode } from \"react\";\nimport type { Variant } from \"@lattice-php/lattice/types/generated\";\n\nexport const variantStyles: Record<Variant, { accent: string; icon: ReactNode }> = {\n primary: {\n accent: \"border-l-lt-primary\",\n icon: <Icon name=\"info\" className=\"size-lt-icon-lg shrink-0 text-lt-primary\" />,\n },\n secondary: {\n accent: \"border-l-lt-secondary\",\n icon: <Icon name=\"info\" className=\"size-lt-icon-lg shrink-0 text-lt-muted-fg\" />,\n },\n success: {\n accent: \"border-l-lt-success\",\n icon: <Icon name=\"circle-check\" className=\"size-lt-icon-lg shrink-0 text-lt-success\" />,\n },\n info: {\n accent: \"border-l-lt-info\",\n icon: <Icon name=\"info\" className=\"size-lt-icon-lg shrink-0 text-lt-info\" />,\n },\n warning: {\n accent: \"border-l-lt-warning\",\n icon: <Icon name=\"circle-alert\" className=\"size-lt-icon-lg shrink-0 text-lt-warning\" />,\n },\n danger: {\n accent: \"border-l-lt-danger\",\n icon: <Icon name=\"circle-x\" className=\"size-lt-icon-lg shrink-0 text-lt-danger\" />,\n },\n};\n"],"mappings":";;;AAIA,IAAa,gBAAsE;CACjF,SAAS;EACP,QAAQ;EACR,MAAM,oBAAC,MAAD;GAAM,MAAK;GAAO,WAAU;EAA4C,CAAA;CAChF;CACA,WAAW;EACT,QAAQ;EACR,MAAM,oBAAC,MAAD;GAAM,MAAK;GAAO,WAAU;EAA6C,CAAA;CACjF;CACA,SAAS;EACP,QAAQ;EACR,MAAM,oBAAC,MAAD;GAAM,MAAK;GAAe,WAAU;EAA4C,CAAA;CACxF;CACA,MAAM;EACJ,QAAQ;EACR,MAAM,oBAAC,MAAD;GAAM,MAAK;GAAO,WAAU;EAAyC,CAAA;CAC7E;CACA,SAAS;EACP,QAAQ;EACR,MAAM,oBAAC,MAAD;GAAM,MAAK;GAAe,WAAU;EAA4C,CAAA;CACxF;CACA,QAAQ;EACN,QAAQ;EACR,MAAM,oBAAC,MAAD;GAAM,MAAK;GAAW,WAAU;EAA2C,CAAA;CACnF;AACF"}
|
|
@@ -103,6 +103,7 @@ export type EffectOf<TType extends string> = string extends TType ? Effect : {
|
|
|
103
103
|
};
|
|
104
104
|
export type Action = {
|
|
105
105
|
confirmation: Confirmation | null;
|
|
106
|
+
emphasis: Emphasis | null;
|
|
106
107
|
endpoint: string | null;
|
|
107
108
|
form: Node<"form"> | null;
|
|
108
109
|
icon: string | null;
|
|
@@ -112,7 +113,7 @@ export type Action = {
|
|
|
112
113
|
modalSide: Side | null;
|
|
113
114
|
modalWidth: ModalWidth | null;
|
|
114
115
|
ref: string | null;
|
|
115
|
-
variant:
|
|
116
|
+
variant: Variant | null;
|
|
116
117
|
};
|
|
117
118
|
export type ActionGroup = {
|
|
118
119
|
label: string | null;
|
|
@@ -135,6 +136,7 @@ export type Avatar = {
|
|
|
135
136
|
src: string | null;
|
|
136
137
|
};
|
|
137
138
|
export type Badge = {
|
|
139
|
+
color: Color | null;
|
|
138
140
|
label: string;
|
|
139
141
|
};
|
|
140
142
|
export type BadgeColumn = {
|
|
@@ -196,6 +198,7 @@ export type Builder = {
|
|
|
196
198
|
};
|
|
197
199
|
export type BulkAction = {
|
|
198
200
|
confirmation: Confirmation | null;
|
|
201
|
+
emphasis: Emphasis | null;
|
|
199
202
|
endpoint: string | null;
|
|
200
203
|
form: Node<"form"> | null;
|
|
201
204
|
icon: string | null;
|
|
@@ -205,20 +208,20 @@ export type BulkAction = {
|
|
|
205
208
|
modalSide: Side | null;
|
|
206
209
|
modalWidth: ModalWidth | null;
|
|
207
210
|
ref: string | null;
|
|
208
|
-
variant:
|
|
211
|
+
variant: Variant | null;
|
|
209
212
|
};
|
|
210
213
|
export type Button = {
|
|
211
214
|
action: Node<"action"> | Node<"action.bulk"> | null;
|
|
212
215
|
buttonType: ButtonType;
|
|
213
216
|
effects: Effect[];
|
|
217
|
+
emphasis: Emphasis | null;
|
|
214
218
|
href: string | null;
|
|
215
219
|
icon: string | null;
|
|
216
220
|
label: string | null;
|
|
217
221
|
method: HttpMethod | null;
|
|
218
|
-
variant:
|
|
222
|
+
variant: Variant | null;
|
|
219
223
|
};
|
|
220
224
|
export type ButtonType = "button" | "submit" | "reset";
|
|
221
|
-
export type ButtonVariant = "default" | "destructive" | "ghost" | "info" | "link" | "outline" | "secondary" | "success";
|
|
222
225
|
export type Callout = {
|
|
223
226
|
action: Node | null;
|
|
224
227
|
dismissible: boolean;
|
|
@@ -602,6 +605,7 @@ export type EffectPropsMap = {
|
|
|
602
605
|
toast: Toast;
|
|
603
606
|
"toggle-sidebar": ToggleSidebar;
|
|
604
607
|
};
|
|
608
|
+
export type Emphasis = "solid" | "outline" | "ghost" | "link";
|
|
605
609
|
export type FieldConditions = {
|
|
606
610
|
readonly disabled: Condition[];
|
|
607
611
|
readonly readOnly: Condition[];
|
|
@@ -679,9 +683,10 @@ export type Form = {
|
|
|
679
683
|
status: string | null;
|
|
680
684
|
submitButton: boolean;
|
|
681
685
|
submitButtons: Node<"button">[] | null;
|
|
686
|
+
submitEmphasis: Emphasis | null;
|
|
682
687
|
submitJustify: Justify | null;
|
|
683
688
|
submitLabel: string | null;
|
|
684
|
-
submitVariant:
|
|
689
|
+
submitVariant: Variant | null;
|
|
685
690
|
validationSummaryLabel: string;
|
|
686
691
|
validationTimeout: number | null;
|
|
687
692
|
};
|
|
@@ -984,12 +989,12 @@ export type Placement = "top" | "bottom" | "right";
|
|
|
984
989
|
export type Progress = {
|
|
985
990
|
color: Color | null;
|
|
986
991
|
max: number;
|
|
992
|
+
shape: ProgressShape;
|
|
987
993
|
showValue: boolean;
|
|
988
994
|
size: Size;
|
|
989
995
|
value: number;
|
|
990
|
-
variant: ProgressVariant;
|
|
991
996
|
};
|
|
992
|
-
export type
|
|
997
|
+
export type ProgressShape = "bar" | "circle";
|
|
993
998
|
export type RawBlock = {
|
|
994
999
|
html: string;
|
|
995
1000
|
};
|
|
@@ -1065,7 +1070,7 @@ export type RichEditor = {
|
|
|
1065
1070
|
value: unknown;
|
|
1066
1071
|
};
|
|
1067
1072
|
export type RowAction = {
|
|
1068
|
-
|
|
1073
|
+
danger: boolean;
|
|
1069
1074
|
icon: string | null;
|
|
1070
1075
|
key: string;
|
|
1071
1076
|
label: string | null;
|
|
@@ -1378,7 +1383,7 @@ export type UiNodeType = "avatar" | "badge" | "button" | "card" | "chart" | "col
|
|
|
1378
1383
|
export type UnreadCount = {
|
|
1379
1384
|
readonly unreadCount: number;
|
|
1380
1385
|
};
|
|
1381
|
-
export type Variant = "success" | "info" | "warning" | "
|
|
1386
|
+
export type Variant = "primary" | "secondary" | "success" | "info" | "warning" | "danger";
|
|
1382
1387
|
export type Width = "full" | "auto" | "sm" | "md" | "lg" | "fill";
|
|
1383
1388
|
export type Wizard = {
|
|
1384
1389
|
orientation: Orientation;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
export declare const actionMenuItemClassName = "flex h-lt-control-sm w-full items-center justify-start gap-2 rounded-lt-sm px-2.5 text-left text-sm font-normal text-lt-popover-fg no-underline decoration-transparent shadow-none transition-colors hover:bg-lt-accent/70 hover:text-lt-popover-fg focus-visible:bg-lt-accent/70 focus-visible:text-lt-popover-fg focus-visible:ring-0 focus-visible:outline-none disabled:pointer-events-none disabled:
|
|
2
|
+
export declare const actionMenuItemClassName = "flex h-lt-control-sm w-full items-center justify-start gap-2 rounded-lt-sm px-2.5 text-left text-sm font-normal text-lt-popover-fg no-underline decoration-transparent shadow-none transition-colors hover:bg-lt-accent/70 hover:text-lt-popover-fg focus-visible:bg-lt-accent/70 focus-visible:text-lt-popover-fg focus-visible:ring-0 focus-visible:outline-none disabled:pointer-events-none disabled:text-lt-disabled-fg [&_svg]:size-lt-icon-sm [&_svg]:text-lt-muted-fg";
|
|
3
3
|
export declare function ActionMenuProvider({ children }: {
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
}): import("react").JSX.Element;
|
|
@@ -2,7 +2,7 @@ import { createContext, useContext } from "react";
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region resources/js/ui/action-menu-context.tsx
|
|
4
4
|
var ActionMenuContext = createContext(false);
|
|
5
|
-
var actionMenuItemClassName = "flex h-lt-control-sm w-full items-center justify-start gap-2 rounded-lt-sm px-2.5 text-left text-sm font-normal text-lt-popover-fg no-underline decoration-transparent shadow-none transition-colors hover:bg-lt-accent/70 hover:text-lt-popover-fg focus-visible:bg-lt-accent/70 focus-visible:text-lt-popover-fg focus-visible:ring-0 focus-visible:outline-none disabled:pointer-events-none disabled:
|
|
5
|
+
var actionMenuItemClassName = "flex h-lt-control-sm w-full items-center justify-start gap-2 rounded-lt-sm px-2.5 text-left text-sm font-normal text-lt-popover-fg no-underline decoration-transparent shadow-none transition-colors hover:bg-lt-accent/70 hover:text-lt-popover-fg focus-visible:bg-lt-accent/70 focus-visible:text-lt-popover-fg focus-visible:ring-0 focus-visible:outline-none disabled:pointer-events-none disabled:text-lt-disabled-fg [&_svg]:size-lt-icon-sm [&_svg]:text-lt-muted-fg";
|
|
6
6
|
function ActionMenuProvider({ children }) {
|
|
7
7
|
return /* @__PURE__ */ jsx(ActionMenuContext.Provider, {
|
|
8
8
|
value: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-menu-context.js","names":[],"sources":["../../resources/js/ui/action-menu-context.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from \"react\";\n\nconst ActionMenuContext = createContext(false);\n\nexport const actionMenuItemClassName =\n \"flex h-lt-control-sm w-full items-center justify-start gap-2 rounded-lt-sm px-2.5 text-left text-sm font-normal text-lt-popover-fg no-underline decoration-transparent shadow-none transition-colors hover:bg-lt-accent/70 hover:text-lt-popover-fg focus-visible:bg-lt-accent/70 focus-visible:text-lt-popover-fg focus-visible:ring-0 focus-visible:outline-none disabled:pointer-events-none disabled:
|
|
1
|
+
{"version":3,"file":"action-menu-context.js","names":[],"sources":["../../resources/js/ui/action-menu-context.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from \"react\";\n\nconst ActionMenuContext = createContext(false);\n\nexport const actionMenuItemClassName =\n \"flex h-lt-control-sm w-full items-center justify-start gap-2 rounded-lt-sm px-2.5 text-left text-sm font-normal text-lt-popover-fg no-underline decoration-transparent shadow-none transition-colors hover:bg-lt-accent/70 hover:text-lt-popover-fg focus-visible:bg-lt-accent/70 focus-visible:text-lt-popover-fg focus-visible:ring-0 focus-visible:outline-none disabled:pointer-events-none disabled:text-lt-disabled-fg [&_svg]:size-lt-icon-sm [&_svg]:text-lt-muted-fg\";\n\nexport function ActionMenuProvider({ children }: { children: ReactNode }) {\n return <ActionMenuContext.Provider value={true}>{children}</ActionMenuContext.Provider>;\n}\n\nexport function useActionMenu(): boolean {\n return useContext(ActionMenuContext);\n}\n"],"mappings":";;;AAEA,IAAM,oBAAoB,cAAc,KAAK;AAE7C,IAAa,0BACX;AAEF,SAAgB,mBAAmB,EAAE,YAAqC;CACxE,OAAO,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;EAAO;CAAqC,CAAA;AACxF;AAEA,SAAgB,gBAAyB;CACvC,OAAO,WAAW,iBAAiB;AACrC"}
|
package/dist/ui/affix-group.js
CHANGED
|
@@ -25,7 +25,7 @@ function AffixSegment({ affix, side, squared = false }) {
|
|
|
25
25
|
function AffixGroup({ prefix, suffix, end, children }) {
|
|
26
26
|
if (!prefix && !suffix && !end) return children("");
|
|
27
27
|
return /* @__PURE__ */ jsxs("div", {
|
|
28
|
-
className: "group flex w-full rounded-lt-sm transition-[color,box-shadow] has-[:focus-visible]:ring-[
|
|
28
|
+
className: "group flex w-full rounded-lt-sm transition-[color,box-shadow] has-[:focus-visible]:ring-[length:var(--lt-ring-width)] has-[:focus-visible]:ring-lt-ring/50",
|
|
29
29
|
"data-slot": "affix-group",
|
|
30
30
|
children: [
|
|
31
31
|
prefix ? /* @__PURE__ */ jsx(AffixSegment, {
|
|
@@ -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({\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-[
|
|
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-[length:var(--lt-ring-width)] 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"}
|
package/dist/ui/badge.d.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Color } from '../types/generated.js';
|
|
2
2
|
import { RendererComponent } from '../core/types.js';
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
declare
|
|
5
|
-
|
|
6
|
-
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
|
-
declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
|
|
8
|
-
asChild?: boolean;
|
|
4
|
+
declare function Badge({ color, className, style, ...props }: Omit<React.ComponentProps<"span">, "color"> & {
|
|
5
|
+
color?: Color | string | null;
|
|
9
6
|
}): React.JSX.Element;
|
|
10
7
|
declare const BadgeComponent: RendererComponent<"badge">;
|
|
11
8
|
export default BadgeComponent;
|
|
12
|
-
export { Badge
|
|
9
|
+
export { Badge };
|