tempest-react-sdk 0.30.0 → 0.31.1
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/components/FilterBar/FilterBar.cjs +2 -0
- package/dist/components/FilterBar/FilterBar.cjs.map +1 -0
- package/dist/components/FilterBar/FilterBar.js +238 -0
- package/dist/components/FilterBar/FilterBar.js.map +1 -0
- package/dist/components/FilterBar/FilterBar.module.cjs +2 -0
- package/dist/components/FilterBar/FilterBar.module.cjs.map +1 -0
- package/dist/components/FilterBar/FilterBar.module.js +20 -0
- package/dist/components/FilterBar/FilterBar.module.js.map +1 -0
- package/dist/components/FilterBar/filter-model.cjs +2 -0
- package/dist/components/FilterBar/filter-model.cjs.map +1 -0
- package/dist/components/FilterBar/filter-model.js +167 -0
- package/dist/components/FilterBar/filter-model.js.map +1 -0
- package/dist/components/Tour/Tour.cjs +2 -0
- package/dist/components/Tour/Tour.cjs.map +1 -0
- package/dist/components/Tour/Tour.js +186 -0
- package/dist/components/Tour/Tour.js.map +1 -0
- package/dist/components/Tour/Tour.module.cjs +2 -0
- package/dist/components/Tour/Tour.module.cjs.map +1 -0
- package/dist/components/Tour/Tour.module.js +21 -0
- package/dist/components/Tour/Tour.module.js.map +1 -0
- package/dist/components/Tour/tour-position.cjs +2 -0
- package/dist/components/Tour/tour-position.cjs.map +1 -0
- package/dist/components/Tour/tour-position.js +105 -0
- package/dist/components/Tour/tour-position.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +181 -0
- package/dist/tempest-react-sdk.js +108 -105
- package/dist/utilities.css +133 -0
- package/package.json +1 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../utils/cn.cjs"),t=require("../VisuallyHidden/VisuallyHidden.cjs"),n=require("./filter-model.cjs"),r=require("./FilterBar.module.cjs");let i=require("react"),a=require("react/jsx-runtime");function o(e){return{field:e.name,operator:n.defaultOperator(e),value:``,to:``}}function s(e){return n.isValueless(e.operator)?{field:e.field,operator:e.operator}:e.operator===`between`?{field:e.field,operator:e.operator,value:[e.value,e.to]}:n.isMulti(e.operator)?{field:e.field,operator:e.operator,value:e.value.split(`,`).map(e=>e.trim()).filter(Boolean)}:{field:e.field,operator:e.operator,value:e.value}}function c({fields:c,value:u,onChange:d,locale:f=`pt-BR`,actions:p,className:m,...h}){let g=n.filterStrings(f),_=(0,i.useId)(),[v,y]=(0,i.useState)(null),b=v?c.find(e=>e.name===v.field):void 0,x=v?s(v):null,S=x!==null&&n.isComplete(x),C=()=>{c.length>0&&y(o(c[0]))},w=()=>{!x||!S||(d([...u,x]),y(null))},T=e=>{d(u.filter((t,n)=>n!==e))};return(0,a.jsxs)(`div`,{className:e.cn(r.default.bar,m),...h,children:[(0,a.jsxs)(`ul`,{className:r.default.chips,children:[u.length===0&&!v&&(0,a.jsx)(`li`,{className:r.default.empty,children:g.empty}),u.map((e,t)=>{let i=n.describeFilter(e,c,f);return(0,a.jsxs)(`li`,{className:r.default.chip,children:[(0,a.jsx)(`span`,{children:i}),(0,a.jsx)(`button`,{type:`button`,className:r.default.remove,"aria-label":g.remove(i),onClick:()=>T(t),children:`×`})]},`${e.field}-${e.operator}-${t}`)})]}),v&&b?(0,a.jsxs)(`div`,{className:r.default.editor,role:`group`,"aria-label":g.add,children:[(0,a.jsxs)(`label`,{className:r.default.control,children:[(0,a.jsx)(t.VisuallyHidden,{children:g.field}),(0,a.jsx)(`select`,{className:r.default.select,value:v.field,onChange:e=>{let t=c.find(t=>t.name===e.target.value);t&&y(o(t))},children:c.map(e=>(0,a.jsx)(`option`,{value:e.name,children:e.label},e.name))})]}),(0,a.jsxs)(`label`,{className:r.default.control,children:[(0,a.jsx)(t.VisuallyHidden,{children:g.operator}),(0,a.jsx)(`select`,{className:r.default.select,value:v.operator,onChange:e=>y({...v,operator:e.target.value,value:``,to:``}),children:n.operatorsFor(b).map(e=>(0,a.jsx)(`option`,{value:e,children:n.operatorLabel(e,f)},e))})]}),!n.isValueless(v.operator)&&(0,a.jsx)(l,{id:`${_}-value`,field:b,draft:v,strings:g,onChange:y}),(0,a.jsx)(`button`,{type:`button`,className:r.default.primary,disabled:!S,onClick:w,children:g.apply}),(0,a.jsx)(`button`,{type:`button`,className:r.default.ghost,onClick:()=>y(null),children:g.cancel})]}):(0,a.jsxs)(`div`,{className:r.default.actions,children:[(0,a.jsxs)(`button`,{type:`button`,className:r.default.secondary,disabled:c.length===0,onClick:C,children:[`+ `,g.add]}),u.length>0&&(0,a.jsx)(`button`,{type:`button`,className:r.default.ghost,onClick:()=>d([]),children:g.clear}),p]}),(0,a.jsx)(t.VisuallyHidden,{"aria-live":`polite`,role:`status`,children:g.active(u.length)})]})}function l({id:e,field:i,draft:o,strings:s,onChange:c}){let l=i.type===`number`?`number`:i.type===`date`?`date`:`text`;return i.type===`select`&&!n.isMulti(o.operator)?(0,a.jsxs)(`label`,{className:r.default.control,children:[(0,a.jsx)(t.VisuallyHidden,{children:s.value}),(0,a.jsxs)(`select`,{id:e,className:r.default.select,value:o.value,onChange:e=>c({...o,value:e.target.value}),children:[(0,a.jsx)(`option`,{value:``,children:`—`}),i.options?.map(e=>(0,a.jsx)(`option`,{value:e.value,children:e.label},e.value))]})]}):i.type===`boolean`?(0,a.jsxs)(`label`,{className:r.default.control,children:[(0,a.jsx)(t.VisuallyHidden,{children:s.value}),(0,a.jsxs)(`select`,{id:e,className:r.default.select,value:o.value,onChange:e=>c({...o,value:e.target.value}),children:[(0,a.jsx)(`option`,{value:``,children:`—`}),(0,a.jsx)(`option`,{value:`true`,children:s.yes}),(0,a.jsx)(`option`,{value:`false`,children:s.no})]})]}):o.operator===`between`?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(`label`,{className:r.default.control,children:[(0,a.jsx)(t.VisuallyHidden,{children:s.from}),(0,a.jsx)(`input`,{id:e,className:r.default.input,type:l,value:o.value,placeholder:s.from,onChange:e=>c({...o,value:e.target.value})})]}),(0,a.jsxs)(`label`,{className:r.default.control,children:[(0,a.jsx)(t.VisuallyHidden,{children:s.to}),(0,a.jsx)(`input`,{className:r.default.input,type:l,value:o.to,placeholder:s.to,onChange:e=>c({...o,to:e.target.value})})]})]}):(0,a.jsxs)(`label`,{className:r.default.control,children:[(0,a.jsx)(t.VisuallyHidden,{children:s.value}),(0,a.jsx)(`input`,{id:e,className:r.default.input,type:l,value:o.value,placeholder:i.placeholder??s.value,onChange:e=>c({...o,value:e.target.value})})]})}exports.FilterBar=c;
|
|
2
|
+
//# sourceMappingURL=FilterBar.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterBar.cjs","names":[],"sources":["../../../src/components/FilterBar/FilterBar.tsx"],"sourcesContent":["import { useId, useState, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { VisuallyHidden } from \"../VisuallyHidden\";\nimport {\n defaultOperator,\n describeFilter,\n filterStrings,\n isComplete,\n isMulti,\n isValueless,\n operatorLabel,\n operatorsFor,\n type Filter,\n type FilterField,\n} from \"./filter-model\";\nimport styles from \"./FilterBar.module.css\";\n\n/** DOM attributes this component redefines. */\ntype OverriddenDomProps = \"children\" | \"onChange\";\n\nexport interface FilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps> {\n /** Fields the user may filter by. */\n fields: readonly FilterField[];\n /** Applied filters. Controlled. */\n value: readonly Filter[];\n /** Next filter set. Combined with AND. */\n onChange: (filters: Filter[]) => void;\n /** Locale for the labels. Default `\"pt-BR\"`. */\n locale?: \"pt-BR\" | \"en\";\n /** Rendered at the end of the bar — a \"save this view\" button, a counter. */\n actions?: ReactNode;\n}\n\n/** The draft filter being built in the editor. */\ninterface Draft {\n field: string;\n operator: Filter[\"operator\"];\n value: string;\n to: string;\n}\n\n/** A fresh draft for a field. */\nfunction draftFor(field: FilterField): Draft {\n return { field: field.name, operator: defaultOperator(field), value: \"\", to: \"\" };\n}\n\n/** Turn a draft into a filter. */\nfunction toFilter(draft: Draft): Filter {\n if (isValueless(draft.operator)) return { field: draft.field, operator: draft.operator };\n if (draft.operator === \"between\") {\n return { field: draft.field, operator: draft.operator, value: [draft.value, draft.to] };\n }\n if (isMulti(draft.operator)) {\n return {\n field: draft.field,\n operator: draft.operator,\n value: draft.value\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean),\n };\n }\n return { field: draft.field, operator: draft.operator, value: draft.value };\n}\n\n/**\n * A row of applied filters, and a small editor to add another.\n *\n * Filters are combined with **AND**, flat — no nested `(a OR b) AND c` groups. That\n * is the shape of nearly every admin list (\"status is paid, created after March,\n * text contains nota\"), and it is what serializes into a URL somebody can send to a\n * colleague. Nested groups need a tree UI with per-node operators and a different\n * serialization; a component trying to be both is clumsy at the common case.\n *\n * Controlled, like the rest of the SDK: it holds the half-typed draft in the editor\n * and nothing else. The applied set is the app's, which is what lets it come from —\n * and go back into — the URL.\n *\n * @example\n * const [filters, setFilters] = useState<Filter[]>(() =>\n * filtersFromSearchParams(new URLSearchParams(location.search), FIELDS),\n * );\n *\n * <FilterBar fields={FIELDS} value={filters} onChange={setFilters} />\n */\nexport function FilterBar({\n fields,\n value,\n onChange,\n locale = \"pt-BR\",\n actions,\n className,\n ...rest\n}: FilterBarProps) {\n const strings = filterStrings(locale);\n const baseId = useId();\n const [draft, setDraft] = useState<Draft | null>(null);\n\n const field = draft ? fields.find((candidate) => candidate.name === draft.field) : undefined;\n const pending = draft ? toFilter(draft) : null;\n const ready = pending !== null && isComplete(pending);\n\n const open = (): void => {\n if (fields.length > 0) setDraft(draftFor(fields[0]));\n };\n\n const apply = (): void => {\n if (!pending || !ready) return;\n onChange([...value, pending]);\n setDraft(null);\n };\n\n const removeAt = (index: number): void => {\n onChange(value.filter((_, position) => position !== index));\n };\n\n return (\n <div className={cn(styles.bar, className)} {...rest}>\n <ul className={styles.chips}>\n {value.length === 0 && !draft && <li className={styles.empty}>{strings.empty}</li>}\n {value.map((filter, index) => {\n const description = describeFilter(filter, fields, locale);\n return (\n <li\n key={`${filter.field}-${filter.operator}-${index}`}\n className={styles.chip}\n >\n <span>{description}</span>\n <button\n type=\"button\"\n className={styles.remove}\n aria-label={strings.remove(description)}\n onClick={() => removeAt(index)}\n >\n ×\n </button>\n </li>\n );\n })}\n </ul>\n\n {draft && field ? (\n <div className={styles.editor} role=\"group\" aria-label={strings.add}>\n <label className={styles.control}>\n <VisuallyHidden>{strings.field}</VisuallyHidden>\n <select\n className={styles.select}\n value={draft.field}\n onChange={(event) => {\n const next = fields.find(\n (candidate) => candidate.name === event.target.value,\n );\n if (next) setDraft(draftFor(next));\n }}\n >\n {fields.map((candidate) => (\n <option key={candidate.name} value={candidate.name}>\n {candidate.label}\n </option>\n ))}\n </select>\n </label>\n\n <label className={styles.control}>\n <VisuallyHidden>{strings.operator}</VisuallyHidden>\n <select\n className={styles.select}\n value={draft.operator}\n onChange={(event) =>\n setDraft({\n ...draft,\n operator: event.target.value as Filter[\"operator\"],\n value: \"\",\n to: \"\",\n })\n }\n >\n {operatorsFor(field).map((operator) => (\n <option key={operator} value={operator}>\n {operatorLabel(operator, locale)}\n </option>\n ))}\n </select>\n </label>\n\n {!isValueless(draft.operator) && (\n <ValueInput\n id={`${baseId}-value`}\n field={field}\n draft={draft}\n strings={strings}\n onChange={setDraft}\n />\n )}\n\n <button\n type=\"button\"\n className={styles.primary}\n disabled={!ready}\n onClick={apply}\n >\n {strings.apply}\n </button>\n <button type=\"button\" className={styles.ghost} onClick={() => setDraft(null)}>\n {strings.cancel}\n </button>\n </div>\n ) : (\n <div className={styles.actions}>\n <button\n type=\"button\"\n className={styles.secondary}\n disabled={fields.length === 0}\n onClick={open}\n >\n + {strings.add}\n </button>\n {value.length > 0 && (\n <button type=\"button\" className={styles.ghost} onClick={() => onChange([])}>\n {strings.clear}\n </button>\n )}\n {actions}\n </div>\n )}\n\n <VisuallyHidden aria-live=\"polite\" role=\"status\">\n {strings.active(value.length)}\n </VisuallyHidden>\n </div>\n );\n}\n\n/**\n * The value input for the draft.\n *\n * The input type follows the **field**, not the operator: a date field gets a date\n * picker even under `between`, where two of them are needed. Typing a date into a\n * text box is the fastest way to produce a filter the backend cannot parse.\n */\nfunction ValueInput({\n id,\n field,\n draft,\n strings,\n onChange,\n}: {\n id: string;\n field: FilterField;\n draft: Draft;\n strings: ReturnType<typeof filterStrings>;\n onChange: (draft: Draft) => void;\n}) {\n const type = field.type === \"number\" ? \"number\" : field.type === \"date\" ? \"date\" : \"text\";\n\n if (field.type === \"select\" && !isMulti(draft.operator)) {\n return (\n <label className={styles.control}>\n <VisuallyHidden>{strings.value}</VisuallyHidden>\n <select\n id={id}\n className={styles.select}\n value={draft.value}\n onChange={(event) => onChange({ ...draft, value: event.target.value })}\n >\n <option value=\"\">—</option>\n {field.options?.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n );\n }\n\n if (field.type === \"boolean\") {\n return (\n <label className={styles.control}>\n <VisuallyHidden>{strings.value}</VisuallyHidden>\n <select\n id={id}\n className={styles.select}\n value={draft.value}\n onChange={(event) => onChange({ ...draft, value: event.target.value })}\n >\n <option value=\"\">—</option>\n <option value=\"true\">{strings.yes}</option>\n <option value=\"false\">{strings.no}</option>\n </select>\n </label>\n );\n }\n\n if (draft.operator === \"between\") {\n return (\n <>\n <label className={styles.control}>\n <VisuallyHidden>{strings.from}</VisuallyHidden>\n <input\n id={id}\n className={styles.input}\n type={type}\n value={draft.value}\n placeholder={strings.from}\n onChange={(event) => onChange({ ...draft, value: event.target.value })}\n />\n </label>\n <label className={styles.control}>\n <VisuallyHidden>{strings.to}</VisuallyHidden>\n <input\n className={styles.input}\n type={type}\n value={draft.to}\n placeholder={strings.to}\n onChange={(event) => onChange({ ...draft, to: event.target.value })}\n />\n </label>\n </>\n );\n }\n\n return (\n <label className={styles.control}>\n <VisuallyHidden>{strings.value}</VisuallyHidden>\n <input\n id={id}\n className={styles.input}\n type={type}\n value={draft.value}\n placeholder={field.placeholder ?? strings.value}\n onChange={(event) => onChange({ ...draft, value: event.target.value })}\n />\n </label>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { cn as e } from "../../utils/cn.js";
|
|
2
|
+
import { VisuallyHidden as t } from "../VisuallyHidden/VisuallyHidden.js";
|
|
3
|
+
import { defaultOperator as n, describeFilter as r, filterStrings as i, isComplete as a, isMulti as o, isValueless as s, operatorLabel as c, operatorsFor as l } from "./filter-model.js";
|
|
4
|
+
import u from "./FilterBar.module.js";
|
|
5
|
+
import { useId as d, useState as f } from "react";
|
|
6
|
+
import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/FilterBar/FilterBar.tsx
|
|
8
|
+
function g(e) {
|
|
9
|
+
return {
|
|
10
|
+
field: e.name,
|
|
11
|
+
operator: n(e),
|
|
12
|
+
value: "",
|
|
13
|
+
to: ""
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function _(e) {
|
|
17
|
+
return s(e.operator) ? {
|
|
18
|
+
field: e.field,
|
|
19
|
+
operator: e.operator
|
|
20
|
+
} : e.operator === "between" ? {
|
|
21
|
+
field: e.field,
|
|
22
|
+
operator: e.operator,
|
|
23
|
+
value: [e.value, e.to]
|
|
24
|
+
} : o(e.operator) ? {
|
|
25
|
+
field: e.field,
|
|
26
|
+
operator: e.operator,
|
|
27
|
+
value: e.value.split(",").map((e) => e.trim()).filter(Boolean)
|
|
28
|
+
} : {
|
|
29
|
+
field: e.field,
|
|
30
|
+
operator: e.operator,
|
|
31
|
+
value: e.value
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function v({ fields: n, value: o, onChange: p, locale: v = "pt-BR", actions: b, className: x, ...S }) {
|
|
35
|
+
let C = i(v), w = d(), [T, E] = f(null), D = T ? n.find((e) => e.name === T.field) : void 0, O = T ? _(T) : null, k = O !== null && a(O), A = () => {
|
|
36
|
+
n.length > 0 && E(g(n[0]));
|
|
37
|
+
}, j = () => {
|
|
38
|
+
!O || !k || (p([...o, O]), E(null));
|
|
39
|
+
}, M = (e) => {
|
|
40
|
+
p(o.filter((t, n) => n !== e));
|
|
41
|
+
};
|
|
42
|
+
return /* @__PURE__ */ h("div", {
|
|
43
|
+
className: e(u.bar, x),
|
|
44
|
+
...S,
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ h("ul", {
|
|
47
|
+
className: u.chips,
|
|
48
|
+
children: [o.length === 0 && !T && /* @__PURE__ */ m("li", {
|
|
49
|
+
className: u.empty,
|
|
50
|
+
children: C.empty
|
|
51
|
+
}), o.map((e, t) => {
|
|
52
|
+
let i = r(e, n, v);
|
|
53
|
+
return /* @__PURE__ */ h("li", {
|
|
54
|
+
className: u.chip,
|
|
55
|
+
children: [/* @__PURE__ */ m("span", { children: i }), /* @__PURE__ */ m("button", {
|
|
56
|
+
type: "button",
|
|
57
|
+
className: u.remove,
|
|
58
|
+
"aria-label": C.remove(i),
|
|
59
|
+
onClick: () => M(t),
|
|
60
|
+
children: "×"
|
|
61
|
+
})]
|
|
62
|
+
}, `${e.field}-${e.operator}-${t}`);
|
|
63
|
+
})]
|
|
64
|
+
}),
|
|
65
|
+
T && D ? /* @__PURE__ */ h("div", {
|
|
66
|
+
className: u.editor,
|
|
67
|
+
role: "group",
|
|
68
|
+
"aria-label": C.add,
|
|
69
|
+
children: [
|
|
70
|
+
/* @__PURE__ */ h("label", {
|
|
71
|
+
className: u.control,
|
|
72
|
+
children: [/* @__PURE__ */ m(t, { children: C.field }), /* @__PURE__ */ m("select", {
|
|
73
|
+
className: u.select,
|
|
74
|
+
value: T.field,
|
|
75
|
+
onChange: (e) => {
|
|
76
|
+
let t = n.find((t) => t.name === e.target.value);
|
|
77
|
+
t && E(g(t));
|
|
78
|
+
},
|
|
79
|
+
children: n.map((e) => /* @__PURE__ */ m("option", {
|
|
80
|
+
value: e.name,
|
|
81
|
+
children: e.label
|
|
82
|
+
}, e.name))
|
|
83
|
+
})]
|
|
84
|
+
}),
|
|
85
|
+
/* @__PURE__ */ h("label", {
|
|
86
|
+
className: u.control,
|
|
87
|
+
children: [/* @__PURE__ */ m(t, { children: C.operator }), /* @__PURE__ */ m("select", {
|
|
88
|
+
className: u.select,
|
|
89
|
+
value: T.operator,
|
|
90
|
+
onChange: (e) => E({
|
|
91
|
+
...T,
|
|
92
|
+
operator: e.target.value,
|
|
93
|
+
value: "",
|
|
94
|
+
to: ""
|
|
95
|
+
}),
|
|
96
|
+
children: l(D).map((e) => /* @__PURE__ */ m("option", {
|
|
97
|
+
value: e,
|
|
98
|
+
children: c(e, v)
|
|
99
|
+
}, e))
|
|
100
|
+
})]
|
|
101
|
+
}),
|
|
102
|
+
!s(T.operator) && /* @__PURE__ */ m(y, {
|
|
103
|
+
id: `${w}-value`,
|
|
104
|
+
field: D,
|
|
105
|
+
draft: T,
|
|
106
|
+
strings: C,
|
|
107
|
+
onChange: E
|
|
108
|
+
}),
|
|
109
|
+
/* @__PURE__ */ m("button", {
|
|
110
|
+
type: "button",
|
|
111
|
+
className: u.primary,
|
|
112
|
+
disabled: !k,
|
|
113
|
+
onClick: j,
|
|
114
|
+
children: C.apply
|
|
115
|
+
}),
|
|
116
|
+
/* @__PURE__ */ m("button", {
|
|
117
|
+
type: "button",
|
|
118
|
+
className: u.ghost,
|
|
119
|
+
onClick: () => E(null),
|
|
120
|
+
children: C.cancel
|
|
121
|
+
})
|
|
122
|
+
]
|
|
123
|
+
}) : /* @__PURE__ */ h("div", {
|
|
124
|
+
className: u.actions,
|
|
125
|
+
children: [
|
|
126
|
+
/* @__PURE__ */ h("button", {
|
|
127
|
+
type: "button",
|
|
128
|
+
className: u.secondary,
|
|
129
|
+
disabled: n.length === 0,
|
|
130
|
+
onClick: A,
|
|
131
|
+
children: ["+ ", C.add]
|
|
132
|
+
}),
|
|
133
|
+
o.length > 0 && /* @__PURE__ */ m("button", {
|
|
134
|
+
type: "button",
|
|
135
|
+
className: u.ghost,
|
|
136
|
+
onClick: () => p([]),
|
|
137
|
+
children: C.clear
|
|
138
|
+
}),
|
|
139
|
+
b
|
|
140
|
+
]
|
|
141
|
+
}),
|
|
142
|
+
/* @__PURE__ */ m(t, {
|
|
143
|
+
"aria-live": "polite",
|
|
144
|
+
role: "status",
|
|
145
|
+
children: C.active(o.length)
|
|
146
|
+
})
|
|
147
|
+
]
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function y({ id: e, field: n, draft: r, strings: i, onChange: a }) {
|
|
151
|
+
let s = n.type === "number" ? "number" : n.type === "date" ? "date" : "text";
|
|
152
|
+
return n.type === "select" && !o(r.operator) ? /* @__PURE__ */ h("label", {
|
|
153
|
+
className: u.control,
|
|
154
|
+
children: [/* @__PURE__ */ m(t, { children: i.value }), /* @__PURE__ */ h("select", {
|
|
155
|
+
id: e,
|
|
156
|
+
className: u.select,
|
|
157
|
+
value: r.value,
|
|
158
|
+
onChange: (e) => a({
|
|
159
|
+
...r,
|
|
160
|
+
value: e.target.value
|
|
161
|
+
}),
|
|
162
|
+
children: [/* @__PURE__ */ m("option", {
|
|
163
|
+
value: "",
|
|
164
|
+
children: "—"
|
|
165
|
+
}), n.options?.map((e) => /* @__PURE__ */ m("option", {
|
|
166
|
+
value: e.value,
|
|
167
|
+
children: e.label
|
|
168
|
+
}, e.value))]
|
|
169
|
+
})]
|
|
170
|
+
}) : n.type === "boolean" ? /* @__PURE__ */ h("label", {
|
|
171
|
+
className: u.control,
|
|
172
|
+
children: [/* @__PURE__ */ m(t, { children: i.value }), /* @__PURE__ */ h("select", {
|
|
173
|
+
id: e,
|
|
174
|
+
className: u.select,
|
|
175
|
+
value: r.value,
|
|
176
|
+
onChange: (e) => a({
|
|
177
|
+
...r,
|
|
178
|
+
value: e.target.value
|
|
179
|
+
}),
|
|
180
|
+
children: [
|
|
181
|
+
/* @__PURE__ */ m("option", {
|
|
182
|
+
value: "",
|
|
183
|
+
children: "—"
|
|
184
|
+
}),
|
|
185
|
+
/* @__PURE__ */ m("option", {
|
|
186
|
+
value: "true",
|
|
187
|
+
children: i.yes
|
|
188
|
+
}),
|
|
189
|
+
/* @__PURE__ */ m("option", {
|
|
190
|
+
value: "false",
|
|
191
|
+
children: i.no
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
})]
|
|
195
|
+
}) : r.operator === "between" ? /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ h("label", {
|
|
196
|
+
className: u.control,
|
|
197
|
+
children: [/* @__PURE__ */ m(t, { children: i.from }), /* @__PURE__ */ m("input", {
|
|
198
|
+
id: e,
|
|
199
|
+
className: u.input,
|
|
200
|
+
type: s,
|
|
201
|
+
value: r.value,
|
|
202
|
+
placeholder: i.from,
|
|
203
|
+
onChange: (e) => a({
|
|
204
|
+
...r,
|
|
205
|
+
value: e.target.value
|
|
206
|
+
})
|
|
207
|
+
})]
|
|
208
|
+
}), /* @__PURE__ */ h("label", {
|
|
209
|
+
className: u.control,
|
|
210
|
+
children: [/* @__PURE__ */ m(t, { children: i.to }), /* @__PURE__ */ m("input", {
|
|
211
|
+
className: u.input,
|
|
212
|
+
type: s,
|
|
213
|
+
value: r.to,
|
|
214
|
+
placeholder: i.to,
|
|
215
|
+
onChange: (e) => a({
|
|
216
|
+
...r,
|
|
217
|
+
to: e.target.value
|
|
218
|
+
})
|
|
219
|
+
})]
|
|
220
|
+
})] }) : /* @__PURE__ */ h("label", {
|
|
221
|
+
className: u.control,
|
|
222
|
+
children: [/* @__PURE__ */ m(t, { children: i.value }), /* @__PURE__ */ m("input", {
|
|
223
|
+
id: e,
|
|
224
|
+
className: u.input,
|
|
225
|
+
type: s,
|
|
226
|
+
value: r.value,
|
|
227
|
+
placeholder: n.placeholder ?? i.value,
|
|
228
|
+
onChange: (e) => a({
|
|
229
|
+
...r,
|
|
230
|
+
value: e.target.value
|
|
231
|
+
})
|
|
232
|
+
})]
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
//#endregion
|
|
236
|
+
export { v as FilterBar };
|
|
237
|
+
|
|
238
|
+
//# sourceMappingURL=FilterBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterBar.js","names":[],"sources":["../../../src/components/FilterBar/FilterBar.tsx"],"sourcesContent":["import { useId, useState, type HTMLAttributes, type ReactNode } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { VisuallyHidden } from \"../VisuallyHidden\";\nimport {\n defaultOperator,\n describeFilter,\n filterStrings,\n isComplete,\n isMulti,\n isValueless,\n operatorLabel,\n operatorsFor,\n type Filter,\n type FilterField,\n} from \"./filter-model\";\nimport styles from \"./FilterBar.module.css\";\n\n/** DOM attributes this component redefines. */\ntype OverriddenDomProps = \"children\" | \"onChange\";\n\nexport interface FilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps> {\n /** Fields the user may filter by. */\n fields: readonly FilterField[];\n /** Applied filters. Controlled. */\n value: readonly Filter[];\n /** Next filter set. Combined with AND. */\n onChange: (filters: Filter[]) => void;\n /** Locale for the labels. Default `\"pt-BR\"`. */\n locale?: \"pt-BR\" | \"en\";\n /** Rendered at the end of the bar — a \"save this view\" button, a counter. */\n actions?: ReactNode;\n}\n\n/** The draft filter being built in the editor. */\ninterface Draft {\n field: string;\n operator: Filter[\"operator\"];\n value: string;\n to: string;\n}\n\n/** A fresh draft for a field. */\nfunction draftFor(field: FilterField): Draft {\n return { field: field.name, operator: defaultOperator(field), value: \"\", to: \"\" };\n}\n\n/** Turn a draft into a filter. */\nfunction toFilter(draft: Draft): Filter {\n if (isValueless(draft.operator)) return { field: draft.field, operator: draft.operator };\n if (draft.operator === \"between\") {\n return { field: draft.field, operator: draft.operator, value: [draft.value, draft.to] };\n }\n if (isMulti(draft.operator)) {\n return {\n field: draft.field,\n operator: draft.operator,\n value: draft.value\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean),\n };\n }\n return { field: draft.field, operator: draft.operator, value: draft.value };\n}\n\n/**\n * A row of applied filters, and a small editor to add another.\n *\n * Filters are combined with **AND**, flat — no nested `(a OR b) AND c` groups. That\n * is the shape of nearly every admin list (\"status is paid, created after March,\n * text contains nota\"), and it is what serializes into a URL somebody can send to a\n * colleague. Nested groups need a tree UI with per-node operators and a different\n * serialization; a component trying to be both is clumsy at the common case.\n *\n * Controlled, like the rest of the SDK: it holds the half-typed draft in the editor\n * and nothing else. The applied set is the app's, which is what lets it come from —\n * and go back into — the URL.\n *\n * @example\n * const [filters, setFilters] = useState<Filter[]>(() =>\n * filtersFromSearchParams(new URLSearchParams(location.search), FIELDS),\n * );\n *\n * <FilterBar fields={FIELDS} value={filters} onChange={setFilters} />\n */\nexport function FilterBar({\n fields,\n value,\n onChange,\n locale = \"pt-BR\",\n actions,\n className,\n ...rest\n}: FilterBarProps) {\n const strings = filterStrings(locale);\n const baseId = useId();\n const [draft, setDraft] = useState<Draft | null>(null);\n\n const field = draft ? fields.find((candidate) => candidate.name === draft.field) : undefined;\n const pending = draft ? toFilter(draft) : null;\n const ready = pending !== null && isComplete(pending);\n\n const open = (): void => {\n if (fields.length > 0) setDraft(draftFor(fields[0]));\n };\n\n const apply = (): void => {\n if (!pending || !ready) return;\n onChange([...value, pending]);\n setDraft(null);\n };\n\n const removeAt = (index: number): void => {\n onChange(value.filter((_, position) => position !== index));\n };\n\n return (\n <div className={cn(styles.bar, className)} {...rest}>\n <ul className={styles.chips}>\n {value.length === 0 && !draft && <li className={styles.empty}>{strings.empty}</li>}\n {value.map((filter, index) => {\n const description = describeFilter(filter, fields, locale);\n return (\n <li\n key={`${filter.field}-${filter.operator}-${index}`}\n className={styles.chip}\n >\n <span>{description}</span>\n <button\n type=\"button\"\n className={styles.remove}\n aria-label={strings.remove(description)}\n onClick={() => removeAt(index)}\n >\n ×\n </button>\n </li>\n );\n })}\n </ul>\n\n {draft && field ? (\n <div className={styles.editor} role=\"group\" aria-label={strings.add}>\n <label className={styles.control}>\n <VisuallyHidden>{strings.field}</VisuallyHidden>\n <select\n className={styles.select}\n value={draft.field}\n onChange={(event) => {\n const next = fields.find(\n (candidate) => candidate.name === event.target.value,\n );\n if (next) setDraft(draftFor(next));\n }}\n >\n {fields.map((candidate) => (\n <option key={candidate.name} value={candidate.name}>\n {candidate.label}\n </option>\n ))}\n </select>\n </label>\n\n <label className={styles.control}>\n <VisuallyHidden>{strings.operator}</VisuallyHidden>\n <select\n className={styles.select}\n value={draft.operator}\n onChange={(event) =>\n setDraft({\n ...draft,\n operator: event.target.value as Filter[\"operator\"],\n value: \"\",\n to: \"\",\n })\n }\n >\n {operatorsFor(field).map((operator) => (\n <option key={operator} value={operator}>\n {operatorLabel(operator, locale)}\n </option>\n ))}\n </select>\n </label>\n\n {!isValueless(draft.operator) && (\n <ValueInput\n id={`${baseId}-value`}\n field={field}\n draft={draft}\n strings={strings}\n onChange={setDraft}\n />\n )}\n\n <button\n type=\"button\"\n className={styles.primary}\n disabled={!ready}\n onClick={apply}\n >\n {strings.apply}\n </button>\n <button type=\"button\" className={styles.ghost} onClick={() => setDraft(null)}>\n {strings.cancel}\n </button>\n </div>\n ) : (\n <div className={styles.actions}>\n <button\n type=\"button\"\n className={styles.secondary}\n disabled={fields.length === 0}\n onClick={open}\n >\n + {strings.add}\n </button>\n {value.length > 0 && (\n <button type=\"button\" className={styles.ghost} onClick={() => onChange([])}>\n {strings.clear}\n </button>\n )}\n {actions}\n </div>\n )}\n\n <VisuallyHidden aria-live=\"polite\" role=\"status\">\n {strings.active(value.length)}\n </VisuallyHidden>\n </div>\n );\n}\n\n/**\n * The value input for the draft.\n *\n * The input type follows the **field**, not the operator: a date field gets a date\n * picker even under `between`, where two of them are needed. Typing a date into a\n * text box is the fastest way to produce a filter the backend cannot parse.\n */\nfunction ValueInput({\n id,\n field,\n draft,\n strings,\n onChange,\n}: {\n id: string;\n field: FilterField;\n draft: Draft;\n strings: ReturnType<typeof filterStrings>;\n onChange: (draft: Draft) => void;\n}) {\n const type = field.type === \"number\" ? \"number\" : field.type === \"date\" ? \"date\" : \"text\";\n\n if (field.type === \"select\" && !isMulti(draft.operator)) {\n return (\n <label className={styles.control}>\n <VisuallyHidden>{strings.value}</VisuallyHidden>\n <select\n id={id}\n className={styles.select}\n value={draft.value}\n onChange={(event) => onChange({ ...draft, value: event.target.value })}\n >\n <option value=\"\">—</option>\n {field.options?.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n );\n }\n\n if (field.type === \"boolean\") {\n return (\n <label className={styles.control}>\n <VisuallyHidden>{strings.value}</VisuallyHidden>\n <select\n id={id}\n className={styles.select}\n value={draft.value}\n onChange={(event) => onChange({ ...draft, value: event.target.value })}\n >\n <option value=\"\">—</option>\n <option value=\"true\">{strings.yes}</option>\n <option value=\"false\">{strings.no}</option>\n </select>\n </label>\n );\n }\n\n if (draft.operator === \"between\") {\n return (\n <>\n <label className={styles.control}>\n <VisuallyHidden>{strings.from}</VisuallyHidden>\n <input\n id={id}\n className={styles.input}\n type={type}\n value={draft.value}\n placeholder={strings.from}\n onChange={(event) => onChange({ ...draft, value: event.target.value })}\n />\n </label>\n <label className={styles.control}>\n <VisuallyHidden>{strings.to}</VisuallyHidden>\n <input\n className={styles.input}\n type={type}\n value={draft.to}\n placeholder={strings.to}\n onChange={(event) => onChange({ ...draft, to: event.target.value })}\n />\n </label>\n </>\n );\n }\n\n return (\n <label className={styles.control}>\n <VisuallyHidden>{strings.value}</VisuallyHidden>\n <input\n id={id}\n className={styles.input}\n type={type}\n value={draft.value}\n placeholder={field.placeholder ?? strings.value}\n onChange={(event) => onChange({ ...draft, value: event.target.value })}\n />\n </label>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=`tempest_bar_UC3Cd`,t=`tempest_chips_9fymy`,n=`tempest_chip_GG8zb`,r=`tempest_empty_UimsO`,i=`tempest_remove_FmPaZ`,a=`tempest_editor_th4Sm`,o=`tempest_control_y8jH6`,s=`tempest_select_yn-Um`,c=`tempest_input_lLEzH`,l=`tempest_actions_s-nBo`,u=`tempest_primary_zW1qN`,d=`tempest_secondary_2wMQS`,f=`tempest_ghost_tDjte`,p={bar:e,chips:t,chip:n,empty:r,remove:i,editor:a,control:o,select:s,input:c,actions:l,primary:u,secondary:d,ghost:f};exports.actions=l,exports.bar=e,exports.chip=n,exports.chips=t,exports.control=o,exports.default=p,exports.editor=a,exports.empty=r,exports.ghost=f,exports.input=c,exports.primary=u,exports.remove=i,exports.secondary=d,exports.select=s;
|
|
2
|
+
//# sourceMappingURL=FilterBar.module.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterBar.module.cjs","names":[],"sources":["../../../src/components/FilterBar/FilterBar.module.css"],"sourcesContent":[".bar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n}\n\n.chips {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: var(--tempest-space-1) var(--tempest-space-1) var(--tempest-space-1)\n var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n}\n\n.empty {\n color: var(--tempest-text-muted);\n}\n\n.remove {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border: none;\n border-radius: var(--tempest-radius-full);\n background: none;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-base);\n line-height: 1;\n cursor: pointer;\n}\n\n.remove:hover {\n background-color: var(--tempest-surface-3);\n color: var(--tempest-text);\n}\n\n/*\n * The editor wraps as a whole on a narrow screen: field, condition and value each\n * keep a usable width instead of shrinking into three unreadable boxes.\n */\n.editor {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n padding: var(--tempest-space-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-surface);\n}\n\n.control {\n display: inline-flex;\n min-width: 0;\n}\n\n.select,\n.input {\n min-width: 7rem;\n max-width: 14rem;\n padding: var(--tempest-space-1) var(--tempest-space-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-bg);\n color: inherit;\n font: inherit;\n}\n\n.select:focus-visible,\n.input:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: -1px;\n}\n\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n}\n\n.primary,\n.secondary,\n.ghost {\n padding: var(--tempest-space-1) var(--tempest-space-3);\n border-radius: var(--tempest-radius-md);\n font: inherit;\n cursor: pointer;\n}\n\n.primary {\n border: none;\n background-color: var(--tempest-primary);\n color: var(--tempest-primary-foreground);\n}\n\n.primary:disabled {\n background-color: var(--tempest-surface-3);\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.secondary {\n border: 1px dashed var(--tempest-border-strong);\n background-color: transparent;\n color: var(--tempest-text);\n}\n\n.secondary:disabled {\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.ghost {\n border: none;\n background: none;\n color: var(--tempest-text-muted);\n text-decoration: underline;\n}\n\n.primary:focus-visible,\n.secondary:focus-visible,\n.ghost:focus-visible,\n.remove:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 1px;\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/components/FilterBar/FilterBar.module.css
|
|
2
|
+
var e = "tempest_bar_UC3Cd", t = "tempest_chips_9fymy", n = "tempest_chip_GG8zb", r = "tempest_empty_UimsO", i = "tempest_remove_FmPaZ", a = "tempest_editor_th4Sm", o = "tempest_control_y8jH6", s = "tempest_select_yn-Um", c = "tempest_input_lLEzH", l = "tempest_actions_s-nBo", u = "tempest_primary_zW1qN", d = "tempest_secondary_2wMQS", f = "tempest_ghost_tDjte", p = {
|
|
3
|
+
bar: e,
|
|
4
|
+
chips: t,
|
|
5
|
+
chip: n,
|
|
6
|
+
empty: r,
|
|
7
|
+
remove: i,
|
|
8
|
+
editor: a,
|
|
9
|
+
control: o,
|
|
10
|
+
select: s,
|
|
11
|
+
input: c,
|
|
12
|
+
actions: l,
|
|
13
|
+
primary: u,
|
|
14
|
+
secondary: d,
|
|
15
|
+
ghost: f
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { l as actions, e as bar, n as chip, t as chips, o as control, p as default, a as editor, r as empty, f as ghost, c as input, u as primary, i as remove, d as secondary, s as select };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=FilterBar.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterBar.module.js","names":[],"sources":["../../../src/components/FilterBar/FilterBar.module.css"],"sourcesContent":[".bar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n}\n\n.chips {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: var(--tempest-space-1) var(--tempest-space-1) var(--tempest-space-1)\n var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n}\n\n.empty {\n color: var(--tempest-text-muted);\n}\n\n.remove {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border: none;\n border-radius: var(--tempest-radius-full);\n background: none;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-base);\n line-height: 1;\n cursor: pointer;\n}\n\n.remove:hover {\n background-color: var(--tempest-surface-3);\n color: var(--tempest-text);\n}\n\n/*\n * The editor wraps as a whole on a narrow screen: field, condition and value each\n * keep a usable width instead of shrinking into three unreadable boxes.\n */\n.editor {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n padding: var(--tempest-space-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-surface);\n}\n\n.control {\n display: inline-flex;\n min-width: 0;\n}\n\n.select,\n.input {\n min-width: 7rem;\n max-width: 14rem;\n padding: var(--tempest-space-1) var(--tempest-space-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-bg);\n color: inherit;\n font: inherit;\n}\n\n.select:focus-visible,\n.input:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: -1px;\n}\n\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n}\n\n.primary,\n.secondary,\n.ghost {\n padding: var(--tempest-space-1) var(--tempest-space-3);\n border-radius: var(--tempest-radius-md);\n font: inherit;\n cursor: pointer;\n}\n\n.primary {\n border: none;\n background-color: var(--tempest-primary);\n color: var(--tempest-primary-foreground);\n}\n\n.primary:disabled {\n background-color: var(--tempest-surface-3);\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.secondary {\n border: 1px dashed var(--tempest-border-strong);\n background-color: transparent;\n color: var(--tempest-text);\n}\n\n.secondary:disabled {\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.ghost {\n border: none;\n background: none;\n color: var(--tempest-text-muted);\n text-decoration: underline;\n}\n\n.primary:focus-visible,\n.secondary:focus-visible,\n.ghost:focus-visible,\n.remove:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 1px;\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e={text:[`contains`,`eq`,`ne`,`empty`,`notEmpty`],number:[`eq`,`ne`,`gt`,`gte`,`lt`,`lte`,`between`],date:[`eq`,`gt`,`gte`,`lt`,`lte`,`between`],select:[`eq`,`ne`,`in`,`empty`,`notEmpty`],boolean:[`eq`]},t=new Set([`empty`,`notEmpty`]),n=new Set([`between`,`in`]),r={"pt-BR":{eq:`é`,ne:`não é`,contains:`contém`,gt:`maior que`,gte:`maior ou igual a`,lt:`menor que`,lte:`menor ou igual a`,between:`entre`,in:`é um de`,empty:`está vazio`,notEmpty:`não está vazio`},en:{eq:`is`,ne:`is not`,contains:`contains`,gt:`greater than`,gte:`at least`,lt:`less than`,lte:`at most`,between:`between`,in:`is any of`,empty:`is empty`,notEmpty:`is not empty`}};function i(t){return[...t.operators??e[t.type]]}function a(e,t=`pt-BR`){return r[t][e]??e}function o(e){return t.has(e)}function s(e){return n.has(e)}function c(e){if(o(e.operator))return!0;let{value:t}=e;return t===void 0?!1:Array.isArray(t)?e.operator===`between`?t.length===2&&t.every(Boolean):t.length>0&&t.every(Boolean):String(t).trim()!==``}function l(e,t){let n=e?.options?.find(e=>e.value===t);return n?n.label:t}function u(e,t,n=`pt-BR`){let r=t.find(t=>t.name===e.field),i=r?.label??e.field,s=a(e.operator,n);if(o(e.operator))return`${i} ${s}`;let c=Array.isArray(e.value)?e.value.map(e=>l(r,e)):[l(r,String(e.value??``))];if(e.operator===`between`&&c.length===2){let e=n===`en`?`and`:`e`;return`${i} ${s} ${c[0]} ${e} ${c[1]}`}return`${i} ${s} ${c.join(`, `)}`}function d(e){return i(e)[0]??`eq`}function f(e){let t=new URLSearchParams;for(let n of e){if(!c(n))continue;let e=Array.isArray(n.value)?n.value.join(`|`):n.value??``;t.append(n.field,o(n.operator)?n.operator:`${n.operator}:${e}`)}return t}function p(e,t){let n=new Map(t.map(e=>[e.name,e])),r=[];for(let[t,a]of e.entries()){let e=n.get(t);if(!e)continue;let l=a.indexOf(`:`),u=l<0?a:a.slice(0,l);if(!i(e).includes(u))continue;if(o(u)){r.push({field:t,operator:u});continue}if(l<0)continue;let d=a.slice(l+1),f={field:t,operator:u,value:s(u)?d.split(`|`):d};c(f)&&r.push(f)}return r}var m={add:`Adicionar filtro`,apply:`Aplicar`,cancel:`Cancelar`,clear:`Limpar filtros`,field:`Campo`,operator:`Condição`,value:`Valor`,from:`De`,to:`Até`,yes:`Sim`,no:`Não`,remove:e=>`Remover filtro: ${e}`,active:e=>e===1?`1 filtro ativo`:`${e} filtros ativos`,empty:`Nenhum filtro`},h={add:`Add filter`,apply:`Apply`,cancel:`Cancel`,clear:`Clear filters`,field:`Field`,operator:`Condition`,value:`Value`,from:`From`,to:`To`,yes:`Yes`,no:`No`,remove:e=>`Remove filter: ${e}`,active:e=>e===1?`1 active filter`:`${e} active filters`,empty:`No filters`};function g(e){return e===`en`?h:m}exports.defaultOperator=d,exports.describeFilter=u,exports.filterStrings=g,exports.filtersFromSearchParams=p,exports.filtersToSearchParams=f,exports.isComplete=c,exports.isMulti=s,exports.isValueless=o,exports.operatorLabel=a,exports.operatorsFor=i;
|
|
2
|
+
//# sourceMappingURL=filter-model.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-model.cjs","names":[],"sources":["../../../src/components/FilterBar/filter-model.ts"],"sourcesContent":["// The filter model behind `FilterBar`: what a field can be compared with, how a\n// filter reads in words, and how a filter set survives a page reload.\n//\n// Flat AND, deliberately. Nested `(a OR b) AND c` groups are a different component\n// with a different UI (a tree with per-node operators) and a different serialization\n// — trying to be both produces a builder that is clumsy for the 95% case, which is\n// \"status is paid, created after March, text contains nota\".\n\n/** Comparison a filter can make. */\nexport type FilterOperator =\n | \"eq\"\n | \"ne\"\n | \"contains\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"between\"\n | \"in\"\n | \"empty\"\n | \"notEmpty\";\n\n/** Kind of value a field holds, which decides its operators and its input. */\nexport type FilterFieldType = \"text\" | \"number\" | \"date\" | \"select\" | \"boolean\";\n\n/** One filterable field. */\nexport interface FilterField {\n /** Key sent to the backend. */\n name: string;\n /** What the user sees. */\n label: string;\n type: FilterFieldType;\n /** Choices for `select`. */\n options?: ReadonlyArray<{ value: string; label: string }>;\n /** Restrict or reorder the operators offered. Defaults per type. */\n operators?: readonly FilterOperator[];\n /** Placeholder for the value input. */\n placeholder?: string;\n}\n\n/** One applied filter. */\nexport interface Filter {\n field: string;\n operator: FilterOperator;\n /** `between` carries a pair; `in` carries a list; `empty`/`notEmpty` carry nothing. */\n value?: string | readonly string[];\n}\n\n/** Operators offered per field type, in the order they appear. */\nconst OPERATORS_BY_TYPE: Record<FilterFieldType, FilterOperator[]> = {\n text: [\"contains\", \"eq\", \"ne\", \"empty\", \"notEmpty\"],\n number: [\"eq\", \"ne\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n date: [\"eq\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n select: [\"eq\", \"ne\", \"in\", \"empty\", \"notEmpty\"],\n boolean: [\"eq\"],\n};\n\n/** Operators that take no value at all. */\nconst VALUELESS: ReadonlySet<FilterOperator> = new Set([\"empty\", \"notEmpty\"]);\n\n/** Operators that take more than one value. */\nconst MULTI: ReadonlySet<FilterOperator> = new Set([\"between\", \"in\"]);\n\n/** Human labels for the operators, per locale. */\nconst OPERATOR_LABELS: Record<\"pt-BR\" | \"en\", Record<FilterOperator, string>> = {\n \"pt-BR\": {\n eq: \"é\",\n ne: \"não é\",\n contains: \"contém\",\n gt: \"maior que\",\n gte: \"maior ou igual a\",\n lt: \"menor que\",\n lte: \"menor ou igual a\",\n between: \"entre\",\n in: \"é um de\",\n empty: \"está vazio\",\n notEmpty: \"não está vazio\",\n },\n en: {\n eq: \"is\",\n ne: \"is not\",\n contains: \"contains\",\n gt: \"greater than\",\n gte: \"at least\",\n lt: \"less than\",\n lte: \"at most\",\n between: \"between\",\n in: \"is any of\",\n empty: \"is empty\",\n notEmpty: \"is not empty\",\n },\n};\n\n/** The operators a field offers. */\nexport function operatorsFor(field: FilterField): FilterOperator[] {\n return [...(field.operators ?? OPERATORS_BY_TYPE[field.type])];\n}\n\n/** Label of an operator. */\nexport function operatorLabel(operator: FilterOperator, locale: \"pt-BR\" | \"en\" = \"pt-BR\"): string {\n return OPERATOR_LABELS[locale][operator] ?? operator;\n}\n\n/** True when the operator needs no value input. */\nexport function isValueless(operator: FilterOperator): boolean {\n return VALUELESS.has(operator);\n}\n\n/** True when the operator takes several values. */\nexport function isMulti(operator: FilterOperator): boolean {\n return MULTI.has(operator);\n}\n\n/**\n * Is this filter complete enough to apply?\n *\n * An incomplete filter is not an error to shout about — it is a half-filled form.\n * The component uses this to keep \"Add\" disabled, which says the same thing without\n * a message nobody asked for.\n */\nexport function isComplete(filter: Filter): boolean {\n if (isValueless(filter.operator)) return true;\n const { value } = filter;\n if (value === undefined) return false;\n if (Array.isArray(value)) {\n if (filter.operator === \"between\") return value.length === 2 && value.every(Boolean);\n return value.length > 0 && value.every(Boolean);\n }\n return String(value).trim() !== \"\";\n}\n\n/** Human text for one value, resolving a `select` option to its label. */\nfunction valueLabel(field: FilterField | undefined, raw: string): string {\n const option = field?.options?.find((candidate) => candidate.value === raw);\n return option ? option.label : raw;\n}\n\n/**\n * One filter, in words: `\"Status é Pago\"`.\n *\n * Used for the chip and for the screen-reader announcement, from the same source —\n * a chip that reads `status=eq:paid` to a sighted user and something else to a\n * screen reader would be two different truths.\n */\nexport function describeFilter(\n filter: Filter,\n fields: readonly FilterField[],\n locale: \"pt-BR\" | \"en\" = \"pt-BR\",\n): string {\n const field = fields.find((candidate) => candidate.name === filter.field);\n const name = field?.label ?? filter.field;\n const operator = operatorLabel(filter.operator, locale);\n if (isValueless(filter.operator)) return `${name} ${operator}`;\n\n const values = Array.isArray(filter.value)\n ? filter.value.map((raw) => valueLabel(field, raw))\n : [valueLabel(field, String(filter.value ?? \"\"))];\n\n if (filter.operator === \"between\" && values.length === 2) {\n const joiner = locale === \"en\" ? \"and\" : \"e\";\n return `${name} ${operator} ${values[0]} ${joiner} ${values[1]}`;\n }\n return `${name} ${operator} ${values.join(\", \")}`;\n}\n\n/** Default operator for a field — the first one it offers. */\nexport function defaultOperator(field: FilterField): FilterOperator {\n return operatorsFor(field)[0] ?? \"eq\";\n}\n\n/**\n * Serialize filters into URL search params.\n *\n * One param per filter, `field=operator:value`, with `|` between the values of a\n * multi-value operator. A filter set that cannot survive a reload is a filter set\n * people re-enter every time they open a link somebody sent them, so this is part\n * of the model rather than something each app reinvents.\n *\n * Repeated fields are kept: `status=eq:paid&status=eq:sent` is two filters, and\n * collapsing them would silently drop one.\n *\n * @param filters - Applied filters.\n * @returns Params ready to merge into a location.\n */\nexport function filtersToSearchParams(filters: readonly Filter[]): URLSearchParams {\n const params = new URLSearchParams();\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n const value = Array.isArray(filter.value) ? filter.value.join(\"|\") : (filter.value ?? \"\");\n params.append(\n filter.field,\n isValueless(filter.operator) ? filter.operator : `${filter.operator}:${value}`,\n );\n }\n return params;\n}\n\n/**\n * Read filters back from URL search params.\n *\n * Anything that does not parse is dropped rather than guessed at: a hand-edited URL\n * is the normal way this input arrives, and rendering a filter the app cannot\n * evaluate would show a list that does not match what the chips claim.\n *\n * @param params - Params from the location.\n * @param fields - Known fields; a param naming anything else is ignored.\n * @returns The filters that parsed.\n */\nexport function filtersFromSearchParams(\n params: URLSearchParams,\n fields: readonly FilterField[],\n): Filter[] {\n const known = new Map(fields.map((field) => [field.name, field]));\n const filters: Filter[] = [];\n\n for (const [name, raw] of params.entries()) {\n const field = known.get(name);\n if (!field) continue;\n\n const separator = raw.indexOf(\":\");\n const operator = (separator < 0 ? raw : raw.slice(0, separator)) as FilterOperator;\n if (!operatorsFor(field).includes(operator)) continue;\n\n if (isValueless(operator)) {\n filters.push({ field: name, operator });\n continue;\n }\n if (separator < 0) continue;\n\n const rest = raw.slice(separator + 1);\n const value = isMulti(operator) ? rest.split(\"|\") : rest;\n const filter: Filter = { field: name, operator, value };\n if (isComplete(filter)) filters.push(filter);\n }\n\n return filters;\n}\n\n/** Labels the bar needs, per locale. */\ninterface FilterStrings {\n add: string;\n apply: string;\n cancel: string;\n clear: string;\n field: string;\n operator: string;\n value: string;\n from: string;\n to: string;\n yes: string;\n no: string;\n remove: (description: string) => string;\n active: (count: number) => string;\n empty: string;\n}\n\nconst PT_BR: FilterStrings = {\n add: \"Adicionar filtro\",\n apply: \"Aplicar\",\n cancel: \"Cancelar\",\n clear: \"Limpar filtros\",\n field: \"Campo\",\n operator: \"Condição\",\n value: \"Valor\",\n from: \"De\",\n to: \"Até\",\n yes: \"Sim\",\n no: \"Não\",\n remove: (description) => `Remover filtro: ${description}`,\n active: (count) => (count === 1 ? \"1 filtro ativo\" : `${count} filtros ativos`),\n empty: \"Nenhum filtro\",\n};\n\nconst EN: FilterStrings = {\n add: \"Add filter\",\n apply: \"Apply\",\n cancel: \"Cancel\",\n clear: \"Clear filters\",\n field: \"Field\",\n operator: \"Condition\",\n value: \"Value\",\n from: \"From\",\n to: \"To\",\n yes: \"Yes\",\n no: \"No\",\n remove: (description) => `Remove filter: ${description}`,\n active: (count) => (count === 1 ? \"1 active filter\" : `${count} active filters`),\n empty: \"No filters\",\n};\n\n/** Locale strings for the bar. */\nexport function filterStrings(locale: \"pt-BR\" | \"en\"): FilterStrings {\n return locale === \"en\" ? EN : PT_BR;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
//#region src/components/FilterBar/filter-model.ts
|
|
2
|
+
var e = {
|
|
3
|
+
text: [
|
|
4
|
+
"contains",
|
|
5
|
+
"eq",
|
|
6
|
+
"ne",
|
|
7
|
+
"empty",
|
|
8
|
+
"notEmpty"
|
|
9
|
+
],
|
|
10
|
+
number: [
|
|
11
|
+
"eq",
|
|
12
|
+
"ne",
|
|
13
|
+
"gt",
|
|
14
|
+
"gte",
|
|
15
|
+
"lt",
|
|
16
|
+
"lte",
|
|
17
|
+
"between"
|
|
18
|
+
],
|
|
19
|
+
date: [
|
|
20
|
+
"eq",
|
|
21
|
+
"gt",
|
|
22
|
+
"gte",
|
|
23
|
+
"lt",
|
|
24
|
+
"lte",
|
|
25
|
+
"between"
|
|
26
|
+
],
|
|
27
|
+
select: [
|
|
28
|
+
"eq",
|
|
29
|
+
"ne",
|
|
30
|
+
"in",
|
|
31
|
+
"empty",
|
|
32
|
+
"notEmpty"
|
|
33
|
+
],
|
|
34
|
+
boolean: ["eq"]
|
|
35
|
+
}, t = /* @__PURE__ */ new Set(["empty", "notEmpty"]), n = /* @__PURE__ */ new Set(["between", "in"]), r = {
|
|
36
|
+
"pt-BR": {
|
|
37
|
+
eq: "é",
|
|
38
|
+
ne: "não é",
|
|
39
|
+
contains: "contém",
|
|
40
|
+
gt: "maior que",
|
|
41
|
+
gte: "maior ou igual a",
|
|
42
|
+
lt: "menor que",
|
|
43
|
+
lte: "menor ou igual a",
|
|
44
|
+
between: "entre",
|
|
45
|
+
in: "é um de",
|
|
46
|
+
empty: "está vazio",
|
|
47
|
+
notEmpty: "não está vazio"
|
|
48
|
+
},
|
|
49
|
+
en: {
|
|
50
|
+
eq: "is",
|
|
51
|
+
ne: "is not",
|
|
52
|
+
contains: "contains",
|
|
53
|
+
gt: "greater than",
|
|
54
|
+
gte: "at least",
|
|
55
|
+
lt: "less than",
|
|
56
|
+
lte: "at most",
|
|
57
|
+
between: "between",
|
|
58
|
+
in: "is any of",
|
|
59
|
+
empty: "is empty",
|
|
60
|
+
notEmpty: "is not empty"
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
function i(t) {
|
|
64
|
+
return [...t.operators ?? e[t.type]];
|
|
65
|
+
}
|
|
66
|
+
function a(e, t = "pt-BR") {
|
|
67
|
+
return r[t][e] ?? e;
|
|
68
|
+
}
|
|
69
|
+
function o(e) {
|
|
70
|
+
return t.has(e);
|
|
71
|
+
}
|
|
72
|
+
function s(e) {
|
|
73
|
+
return n.has(e);
|
|
74
|
+
}
|
|
75
|
+
function c(e) {
|
|
76
|
+
if (o(e.operator)) return !0;
|
|
77
|
+
let { value: t } = e;
|
|
78
|
+
return t === void 0 ? !1 : Array.isArray(t) ? e.operator === "between" ? t.length === 2 && t.every(Boolean) : t.length > 0 && t.every(Boolean) : String(t).trim() !== "";
|
|
79
|
+
}
|
|
80
|
+
function l(e, t) {
|
|
81
|
+
let n = e?.options?.find((e) => e.value === t);
|
|
82
|
+
return n ? n.label : t;
|
|
83
|
+
}
|
|
84
|
+
function u(e, t, n = "pt-BR") {
|
|
85
|
+
let r = t.find((t) => t.name === e.field), i = r?.label ?? e.field, s = a(e.operator, n);
|
|
86
|
+
if (o(e.operator)) return `${i} ${s}`;
|
|
87
|
+
let c = Array.isArray(e.value) ? e.value.map((e) => l(r, e)) : [l(r, String(e.value ?? ""))];
|
|
88
|
+
if (e.operator === "between" && c.length === 2) {
|
|
89
|
+
let e = n === "en" ? "and" : "e";
|
|
90
|
+
return `${i} ${s} ${c[0]} ${e} ${c[1]}`;
|
|
91
|
+
}
|
|
92
|
+
return `${i} ${s} ${c.join(", ")}`;
|
|
93
|
+
}
|
|
94
|
+
function d(e) {
|
|
95
|
+
return i(e)[0] ?? "eq";
|
|
96
|
+
}
|
|
97
|
+
function f(e) {
|
|
98
|
+
let t = new URLSearchParams();
|
|
99
|
+
for (let n of e) {
|
|
100
|
+
if (!c(n)) continue;
|
|
101
|
+
let e = Array.isArray(n.value) ? n.value.join("|") : n.value ?? "";
|
|
102
|
+
t.append(n.field, o(n.operator) ? n.operator : `${n.operator}:${e}`);
|
|
103
|
+
}
|
|
104
|
+
return t;
|
|
105
|
+
}
|
|
106
|
+
function p(e, t) {
|
|
107
|
+
let n = new Map(t.map((e) => [e.name, e])), r = [];
|
|
108
|
+
for (let [t, a] of e.entries()) {
|
|
109
|
+
let e = n.get(t);
|
|
110
|
+
if (!e) continue;
|
|
111
|
+
let l = a.indexOf(":"), u = l < 0 ? a : a.slice(0, l);
|
|
112
|
+
if (!i(e).includes(u)) continue;
|
|
113
|
+
if (o(u)) {
|
|
114
|
+
r.push({
|
|
115
|
+
field: t,
|
|
116
|
+
operator: u
|
|
117
|
+
});
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (l < 0) continue;
|
|
121
|
+
let d = a.slice(l + 1), f = {
|
|
122
|
+
field: t,
|
|
123
|
+
operator: u,
|
|
124
|
+
value: s(u) ? d.split("|") : d
|
|
125
|
+
};
|
|
126
|
+
c(f) && r.push(f);
|
|
127
|
+
}
|
|
128
|
+
return r;
|
|
129
|
+
}
|
|
130
|
+
var m = {
|
|
131
|
+
add: "Adicionar filtro",
|
|
132
|
+
apply: "Aplicar",
|
|
133
|
+
cancel: "Cancelar",
|
|
134
|
+
clear: "Limpar filtros",
|
|
135
|
+
field: "Campo",
|
|
136
|
+
operator: "Condição",
|
|
137
|
+
value: "Valor",
|
|
138
|
+
from: "De",
|
|
139
|
+
to: "Até",
|
|
140
|
+
yes: "Sim",
|
|
141
|
+
no: "Não",
|
|
142
|
+
remove: (e) => `Remover filtro: ${e}`,
|
|
143
|
+
active: (e) => e === 1 ? "1 filtro ativo" : `${e} filtros ativos`,
|
|
144
|
+
empty: "Nenhum filtro"
|
|
145
|
+
}, h = {
|
|
146
|
+
add: "Add filter",
|
|
147
|
+
apply: "Apply",
|
|
148
|
+
cancel: "Cancel",
|
|
149
|
+
clear: "Clear filters",
|
|
150
|
+
field: "Field",
|
|
151
|
+
operator: "Condition",
|
|
152
|
+
value: "Value",
|
|
153
|
+
from: "From",
|
|
154
|
+
to: "To",
|
|
155
|
+
yes: "Yes",
|
|
156
|
+
no: "No",
|
|
157
|
+
remove: (e) => `Remove filter: ${e}`,
|
|
158
|
+
active: (e) => e === 1 ? "1 active filter" : `${e} active filters`,
|
|
159
|
+
empty: "No filters"
|
|
160
|
+
};
|
|
161
|
+
function g(e) {
|
|
162
|
+
return e === "en" ? h : m;
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
export { d as defaultOperator, u as describeFilter, g as filterStrings, p as filtersFromSearchParams, f as filtersToSearchParams, c as isComplete, s as isMulti, o as isValueless, a as operatorLabel, i as operatorsFor };
|
|
166
|
+
|
|
167
|
+
//# sourceMappingURL=filter-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-model.js","names":[],"sources":["../../../src/components/FilterBar/filter-model.ts"],"sourcesContent":["// The filter model behind `FilterBar`: what a field can be compared with, how a\n// filter reads in words, and how a filter set survives a page reload.\n//\n// Flat AND, deliberately. Nested `(a OR b) AND c` groups are a different component\n// with a different UI (a tree with per-node operators) and a different serialization\n// — trying to be both produces a builder that is clumsy for the 95% case, which is\n// \"status is paid, created after March, text contains nota\".\n\n/** Comparison a filter can make. */\nexport type FilterOperator =\n | \"eq\"\n | \"ne\"\n | \"contains\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"between\"\n | \"in\"\n | \"empty\"\n | \"notEmpty\";\n\n/** Kind of value a field holds, which decides its operators and its input. */\nexport type FilterFieldType = \"text\" | \"number\" | \"date\" | \"select\" | \"boolean\";\n\n/** One filterable field. */\nexport interface FilterField {\n /** Key sent to the backend. */\n name: string;\n /** What the user sees. */\n label: string;\n type: FilterFieldType;\n /** Choices for `select`. */\n options?: ReadonlyArray<{ value: string; label: string }>;\n /** Restrict or reorder the operators offered. Defaults per type. */\n operators?: readonly FilterOperator[];\n /** Placeholder for the value input. */\n placeholder?: string;\n}\n\n/** One applied filter. */\nexport interface Filter {\n field: string;\n operator: FilterOperator;\n /** `between` carries a pair; `in` carries a list; `empty`/`notEmpty` carry nothing. */\n value?: string | readonly string[];\n}\n\n/** Operators offered per field type, in the order they appear. */\nconst OPERATORS_BY_TYPE: Record<FilterFieldType, FilterOperator[]> = {\n text: [\"contains\", \"eq\", \"ne\", \"empty\", \"notEmpty\"],\n number: [\"eq\", \"ne\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n date: [\"eq\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n select: [\"eq\", \"ne\", \"in\", \"empty\", \"notEmpty\"],\n boolean: [\"eq\"],\n};\n\n/** Operators that take no value at all. */\nconst VALUELESS: ReadonlySet<FilterOperator> = new Set([\"empty\", \"notEmpty\"]);\n\n/** Operators that take more than one value. */\nconst MULTI: ReadonlySet<FilterOperator> = new Set([\"between\", \"in\"]);\n\n/** Human labels for the operators, per locale. */\nconst OPERATOR_LABELS: Record<\"pt-BR\" | \"en\", Record<FilterOperator, string>> = {\n \"pt-BR\": {\n eq: \"é\",\n ne: \"não é\",\n contains: \"contém\",\n gt: \"maior que\",\n gte: \"maior ou igual a\",\n lt: \"menor que\",\n lte: \"menor ou igual a\",\n between: \"entre\",\n in: \"é um de\",\n empty: \"está vazio\",\n notEmpty: \"não está vazio\",\n },\n en: {\n eq: \"is\",\n ne: \"is not\",\n contains: \"contains\",\n gt: \"greater than\",\n gte: \"at least\",\n lt: \"less than\",\n lte: \"at most\",\n between: \"between\",\n in: \"is any of\",\n empty: \"is empty\",\n notEmpty: \"is not empty\",\n },\n};\n\n/** The operators a field offers. */\nexport function operatorsFor(field: FilterField): FilterOperator[] {\n return [...(field.operators ?? OPERATORS_BY_TYPE[field.type])];\n}\n\n/** Label of an operator. */\nexport function operatorLabel(operator: FilterOperator, locale: \"pt-BR\" | \"en\" = \"pt-BR\"): string {\n return OPERATOR_LABELS[locale][operator] ?? operator;\n}\n\n/** True when the operator needs no value input. */\nexport function isValueless(operator: FilterOperator): boolean {\n return VALUELESS.has(operator);\n}\n\n/** True when the operator takes several values. */\nexport function isMulti(operator: FilterOperator): boolean {\n return MULTI.has(operator);\n}\n\n/**\n * Is this filter complete enough to apply?\n *\n * An incomplete filter is not an error to shout about — it is a half-filled form.\n * The component uses this to keep \"Add\" disabled, which says the same thing without\n * a message nobody asked for.\n */\nexport function isComplete(filter: Filter): boolean {\n if (isValueless(filter.operator)) return true;\n const { value } = filter;\n if (value === undefined) return false;\n if (Array.isArray(value)) {\n if (filter.operator === \"between\") return value.length === 2 && value.every(Boolean);\n return value.length > 0 && value.every(Boolean);\n }\n return String(value).trim() !== \"\";\n}\n\n/** Human text for one value, resolving a `select` option to its label. */\nfunction valueLabel(field: FilterField | undefined, raw: string): string {\n const option = field?.options?.find((candidate) => candidate.value === raw);\n return option ? option.label : raw;\n}\n\n/**\n * One filter, in words: `\"Status é Pago\"`.\n *\n * Used for the chip and for the screen-reader announcement, from the same source —\n * a chip that reads `status=eq:paid` to a sighted user and something else to a\n * screen reader would be two different truths.\n */\nexport function describeFilter(\n filter: Filter,\n fields: readonly FilterField[],\n locale: \"pt-BR\" | \"en\" = \"pt-BR\",\n): string {\n const field = fields.find((candidate) => candidate.name === filter.field);\n const name = field?.label ?? filter.field;\n const operator = operatorLabel(filter.operator, locale);\n if (isValueless(filter.operator)) return `${name} ${operator}`;\n\n const values = Array.isArray(filter.value)\n ? filter.value.map((raw) => valueLabel(field, raw))\n : [valueLabel(field, String(filter.value ?? \"\"))];\n\n if (filter.operator === \"between\" && values.length === 2) {\n const joiner = locale === \"en\" ? \"and\" : \"e\";\n return `${name} ${operator} ${values[0]} ${joiner} ${values[1]}`;\n }\n return `${name} ${operator} ${values.join(\", \")}`;\n}\n\n/** Default operator for a field — the first one it offers. */\nexport function defaultOperator(field: FilterField): FilterOperator {\n return operatorsFor(field)[0] ?? \"eq\";\n}\n\n/**\n * Serialize filters into URL search params.\n *\n * One param per filter, `field=operator:value`, with `|` between the values of a\n * multi-value operator. A filter set that cannot survive a reload is a filter set\n * people re-enter every time they open a link somebody sent them, so this is part\n * of the model rather than something each app reinvents.\n *\n * Repeated fields are kept: `status=eq:paid&status=eq:sent` is two filters, and\n * collapsing them would silently drop one.\n *\n * @param filters - Applied filters.\n * @returns Params ready to merge into a location.\n */\nexport function filtersToSearchParams(filters: readonly Filter[]): URLSearchParams {\n const params = new URLSearchParams();\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n const value = Array.isArray(filter.value) ? filter.value.join(\"|\") : (filter.value ?? \"\");\n params.append(\n filter.field,\n isValueless(filter.operator) ? filter.operator : `${filter.operator}:${value}`,\n );\n }\n return params;\n}\n\n/**\n * Read filters back from URL search params.\n *\n * Anything that does not parse is dropped rather than guessed at: a hand-edited URL\n * is the normal way this input arrives, and rendering a filter the app cannot\n * evaluate would show a list that does not match what the chips claim.\n *\n * @param params - Params from the location.\n * @param fields - Known fields; a param naming anything else is ignored.\n * @returns The filters that parsed.\n */\nexport function filtersFromSearchParams(\n params: URLSearchParams,\n fields: readonly FilterField[],\n): Filter[] {\n const known = new Map(fields.map((field) => [field.name, field]));\n const filters: Filter[] = [];\n\n for (const [name, raw] of params.entries()) {\n const field = known.get(name);\n if (!field) continue;\n\n const separator = raw.indexOf(\":\");\n const operator = (separator < 0 ? raw : raw.slice(0, separator)) as FilterOperator;\n if (!operatorsFor(field).includes(operator)) continue;\n\n if (isValueless(operator)) {\n filters.push({ field: name, operator });\n continue;\n }\n if (separator < 0) continue;\n\n const rest = raw.slice(separator + 1);\n const value = isMulti(operator) ? rest.split(\"|\") : rest;\n const filter: Filter = { field: name, operator, value };\n if (isComplete(filter)) filters.push(filter);\n }\n\n return filters;\n}\n\n/** Labels the bar needs, per locale. */\ninterface FilterStrings {\n add: string;\n apply: string;\n cancel: string;\n clear: string;\n field: string;\n operator: string;\n value: string;\n from: string;\n to: string;\n yes: string;\n no: string;\n remove: (description: string) => string;\n active: (count: number) => string;\n empty: string;\n}\n\nconst PT_BR: FilterStrings = {\n add: \"Adicionar filtro\",\n apply: \"Aplicar\",\n cancel: \"Cancelar\",\n clear: \"Limpar filtros\",\n field: \"Campo\",\n operator: \"Condição\",\n value: \"Valor\",\n from: \"De\",\n to: \"Até\",\n yes: \"Sim\",\n no: \"Não\",\n remove: (description) => `Remover filtro: ${description}`,\n active: (count) => (count === 1 ? \"1 filtro ativo\" : `${count} filtros ativos`),\n empty: \"Nenhum filtro\",\n};\n\nconst EN: FilterStrings = {\n add: \"Add filter\",\n apply: \"Apply\",\n cancel: \"Cancel\",\n clear: \"Clear filters\",\n field: \"Field\",\n operator: \"Condition\",\n value: \"Value\",\n from: \"From\",\n to: \"To\",\n yes: \"Yes\",\n no: \"No\",\n remove: (description) => `Remove filter: ${description}`,\n active: (count) => (count === 1 ? \"1 active filter\" : `${count} active filters`),\n empty: \"No filters\",\n};\n\n/** Locale strings for the bar. */\nexport function filterStrings(locale: \"pt-BR\" | \"en\"): FilterStrings {\n return locale === \"en\" ? EN : PT_BR;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../utils/cn.cjs"),t=require("../../hooks/use-focus-trap.cjs"),n=require("./tour-position.cjs"),r=require("./Tour.module.cjs");let i=require("react"),a=require("react/jsx-runtime");var o={next:`Próximo`,back:`Voltar`,finish:`Concluir`,skip:`Pular`,close:`Fechar tour`,progress:(e,t)=>`Passo ${e} de ${t}`},s={next:`Next`,back:`Back`,finish:`Done`,skip:`Skip`,close:`Close tour`,progress:(e,t)=>`Step ${e} of ${t}`};function c({steps:c,open:l,onClose:u,onFinish:d,index:f,onIndexChange:p,locale:m=`pt-BR`,spotlightPadding:h=4,className:g}){let _=m===`en`?s:o,[v,y]=(0,i.useState)(0),b=Math.min(f??v,Math.max(0,c.length-1)),x=c[b],S=(0,i.useRef)(null),[C,w]=(0,i.useState)(null),[T,E]=(0,i.useState)({placement:`center`,top:0,left:0}),[D,O]=(0,i.useState)({width:0,height:0}),k=(0,i.useId)(),A=(0,i.useId)();t.useFocusTrap(S,l);let j=(0,i.useCallback)(e=>{f===void 0&&y(e),p?.(e)},[f,p]);(0,i.useEffect)(()=>{l&&f===void 0&&y(0)},[l,f]);let M=(0,i.useCallback)(()=>{if(!l||!x)return;let e=(x.target?document.querySelector(x.target):null)?.getBoundingClientRect()??null;w(e?{top:e.top,left:e.left,width:e.width,height:e.height}:null);let t={width:S.current?.offsetWidth??320,height:S.current?.offsetHeight??160},r={width:window.innerWidth,height:window.innerHeight};O(r),E(n.placeCard({target:e?{top:e.top,left:e.left,width:e.width,height:e.height}:null,card:t,viewport:r,preferred:x.placement}))},[l,x]);if((0,i.useLayoutEffect)(()=>{if(!l||!x)return;(x.target?document.querySelector(x.target):null)?.scrollIntoView({block:`center`,inline:`nearest`,behavior:`smooth`});let e=requestAnimationFrame(M);return()=>cancelAnimationFrame(e)},[l,x,M]),(0,i.useEffect)(()=>{if(l)return window.addEventListener(`resize`,M),window.addEventListener(`scroll`,M,!0),()=>{window.removeEventListener(`resize`,M),window.removeEventListener(`scroll`,M,!0)}},[l,M]),(0,i.useEffect)(()=>{l&&S.current?.focus()},[l,b]),!l||!x)return null;let N=b===c.length-1,P=()=>{d?.(),u()};return(0,a.jsxs)(`div`,{className:r.default.root,"data-placement":T.placement,children:[n.backdropRects(C,D,h).map((e,t)=>(0,a.jsx)(`div`,{className:r.default.backdrop,style:{top:e.top,left:e.left,width:e.width,height:e.height},onClick:u},t)),C&&(0,a.jsx)(`div`,{className:r.default.spotlight,style:{top:C.top-h,left:C.left-h,width:C.width+h*2,height:C.height+h*2}}),(0,a.jsxs)(`div`,{ref:S,className:e.cn(r.default.card,g),style:{top:T.top,left:T.left},role:`dialog`,"aria-modal":`true`,"aria-labelledby":x.title?k:void 0,"aria-describedby":A,tabIndex:-1,onKeyDown:e=>{if(e.key===`Escape`){e.stopPropagation(),u();return}e.key===`ArrowRight`&&!N&&(e.preventDefault(),j(b+1)),e.key===`ArrowLeft`&&b>0&&(e.preventDefault(),j(b-1))},children:[(0,a.jsxs)(`div`,{className:r.default.header,children:[(0,a.jsx)(`span`,{className:r.default.progress,children:_.progress(b+1,c.length)}),(0,a.jsx)(`button`,{type:`button`,className:r.default.close,"aria-label":_.close,onClick:u,children:`×`})]}),x.title&&(0,a.jsx)(`h2`,{className:r.default.title,id:k,children:x.title}),(0,a.jsx)(`div`,{className:r.default.body,id:A,children:x.body}),(0,a.jsxs)(`div`,{className:r.default.footer,children:[!N&&(0,a.jsx)(`button`,{type:`button`,className:r.default.skip,onClick:u,children:_.skip}),(0,a.jsxs)(`div`,{className:r.default.actions,children:[b>0&&(0,a.jsx)(`button`,{type:`button`,className:r.default.secondary,onClick:()=>j(b-1),children:_.back}),(0,a.jsx)(`button`,{type:`button`,className:r.default.primary,onClick:()=>N?P():j(b+1),children:N?_.finish:_.next})]})]})]})]})}exports.Tour=c;
|
|
2
|
+
//# sourceMappingURL=Tour.cjs.map
|