@tetrascience-npm/tetrascience-react-ui 1.0.0-beta.157.1 → 1.0.0-beta.159.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.
Files changed (77) hide show
  1. package/README.md +113 -0
  2. package/dist/components/ai/streamdown-plugins.cjs +1 -1
  3. package/dist/components/ai/streamdown-plugins.cjs.map +1 -1
  4. package/dist/components/ai/streamdown-plugins.d.ts +5 -1
  5. package/dist/components/ai/streamdown-plugins.js +22 -11
  6. package/dist/components/ai/streamdown-plugins.js.map +1 -1
  7. package/dist/components/ai/use-streamdown-plugins.cjs +1 -1
  8. package/dist/components/ai/use-streamdown-plugins.cjs.map +1 -1
  9. package/dist/components/ai/use-streamdown-plugins.js +7 -7
  10. package/dist/components/ai/use-streamdown-plugins.js.map +1 -1
  11. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs +1 -1
  12. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs.map +1 -1
  13. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.d.ts +5 -1
  14. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js +32 -30
  15. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js.map +1 -1
  16. package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs +1 -1
  17. package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs.map +1 -1
  18. package/dist/components/composed/PlateMapEditor/PlateMapEditor.d.ts +269 -13
  19. package/dist/components/composed/PlateMapEditor/PlateMapEditor.js +392 -310
  20. package/dist/components/composed/PlateMapEditor/PlateMapEditor.js.map +1 -1
  21. package/dist/components/composed/PlateMapEditor/PlateMapForm.cjs +1 -1
  22. package/dist/components/composed/PlateMapEditor/PlateMapForm.cjs.map +1 -1
  23. package/dist/components/composed/PlateMapEditor/PlateMapForm.d.ts +5 -1
  24. package/dist/components/composed/PlateMapEditor/PlateMapForm.js +19 -15
  25. package/dist/components/composed/PlateMapEditor/PlateMapForm.js.map +1 -1
  26. package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs +1 -1
  27. package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs.map +1 -1
  28. package/dist/components/composed/PlateMapEditor/PlateMapGrid.d.ts +12 -1
  29. package/dist/components/composed/PlateMapEditor/PlateMapGrid.js +69 -63
  30. package/dist/components/composed/PlateMapEditor/PlateMapGrid.js.map +1 -1
  31. package/dist/components/composed/PlateMapEditor/PlateMapManifest.cjs +1 -1
  32. package/dist/components/composed/PlateMapEditor/PlateMapManifest.cjs.map +1 -1
  33. package/dist/components/composed/PlateMapEditor/PlateMapManifest.d.ts +13 -4
  34. package/dist/components/composed/PlateMapEditor/PlateMapManifest.js +38 -29
  35. package/dist/components/composed/PlateMapEditor/PlateMapManifest.js.map +1 -1
  36. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs +1 -1
  37. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs.map +1 -1
  38. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.d.ts +6 -1
  39. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js +490 -275
  40. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js.map +1 -1
  41. package/dist/components/composed/PlateMapEditor/WellLegend.cjs +1 -1
  42. package/dist/components/composed/PlateMapEditor/WellLegend.cjs.map +1 -1
  43. package/dist/components/composed/PlateMapEditor/WellLegend.d.ts +8 -2
  44. package/dist/components/composed/PlateMapEditor/WellLegend.js +8 -7
  45. package/dist/components/composed/PlateMapEditor/WellLegend.js.map +1 -1
  46. package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs +1 -1
  47. package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs.map +1 -1
  48. package/dist/components/composed/PlateMapEditor/WellManifestTable.d.ts +6 -2
  49. package/dist/components/composed/PlateMapEditor/WellManifestTable.js +288 -256
  50. package/dist/components/composed/PlateMapEditor/WellManifestTable.js.map +1 -1
  51. package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs +1 -1
  52. package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs.map +1 -1
  53. package/dist/components/composed/PlateMapEditor/WellMetadataForm.d.ts +5 -1
  54. package/dist/components/composed/PlateMapEditor/WellMetadataForm.js +61 -66
  55. package/dist/components/composed/PlateMapEditor/WellMetadataForm.js.map +1 -1
  56. package/dist/components/composed/PlateMapEditor/WellQuickPaint.cjs +2 -0
  57. package/dist/components/composed/PlateMapEditor/WellQuickPaint.cjs.map +1 -0
  58. package/dist/components/composed/PlateMapEditor/WellQuickPaint.d.ts +23 -0
  59. package/dist/components/composed/PlateMapEditor/WellQuickPaint.js +75 -0
  60. package/dist/components/composed/PlateMapEditor/WellQuickPaint.js.map +1 -0
  61. package/dist/components/composed/PlateMapEditor/index.d.ts +6 -2
  62. package/dist/components/composed/PlateMapEditor/types.d.ts +65 -0
  63. package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.cjs +2 -0
  64. package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.cjs.map +1 -0
  65. package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.d.ts +109 -0
  66. package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.js +246 -0
  67. package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.js.map +1 -0
  68. package/dist/composed/PlateMapEditor.cjs +1 -1
  69. package/dist/composed/PlateMapEditor.js +48 -42
  70. package/dist/composed/PlateMapEditor.js.map +1 -1
  71. package/dist/index.cjs +1 -1
  72. package/dist/index.css +1 -1
  73. package/dist/index.js +701 -695
  74. package/dist/index.js.map +1 -1
  75. package/dist/index.scoped.css +1 -1
  76. package/dist/index.tailwind.css +1 -1
  77. package/package.json +1 -1
package/README.md CHANGED
@@ -306,6 +306,119 @@ For AI-assisted consuming apps, add a short instruction like this to the app's `
306
306
  Use `ProcessFlow` from `@tetrascience-npm/tetrascience-react-ui` for multi-step workflow visualization. Do not build a custom stepper for upload, validation, review, approval, processing, or setup flows. Parent components own the workflow state and pass `steps: ProcessFlowStep[]`; each step status must be one of `PROCESS_FLOW_STEP_STATUSES`. Use `selectedStepId` only for the viewed/selected step. Keep completion/error side effects in the parent workflow code, not inside `ProcessFlow`.
307
307
  ```
308
308
 
309
+ #### PlateMapEditor
310
+
311
+ `PlateMapEditor` is the standard plate-map editing surface — a metadata form, an
312
+ interactive plate grid, and a sample manifest, wired together by a staged-edit
313
+ controller. Use it as-is for the default layout; tune it with props; and drop to
314
+ `usePlateMapEditorState` only when you need a layout the props can't express.
315
+
316
+ ```tsx
317
+ import { PlateMapEditor } from "@tetrascience-npm/tetrascience-react-ui";
318
+
319
+ function PlateScreen() {
320
+ const [values, setValues] = React.useState(new Map());
321
+ const [selection, setSelection] = React.useState(new Set());
322
+
323
+ return (
324
+ <PlateMapEditor
325
+ format="96"
326
+ values={values}
327
+ onChange={setValues}
328
+ selection={selection}
329
+ onSelectionChange={setSelection}
330
+ fields={FIELDS}
331
+ tableColumns={COLUMNS}
332
+ />
333
+ );
334
+ }
335
+ ```
336
+
337
+ ##### Choosing a level
338
+
339
+ | You need | Use |
340
+ | --- | --- |
341
+ | The standard surface, tuned by props | `PlateMapEditor` |
342
+ | The form somewhere the editor can't reach | `PlateMapEditor` + `hideForm` + the imperative handle |
343
+ | A layout no prop combination expresses | `usePlateMapEditorState` + `PlateMapForm` / `PlateMapGrid` / `PlateMapManifest` |
344
+
345
+ Dropping to the hook keeps the apply/clear semantics, plate scoping, and barcode
346
+ stamping — you only take over layout. Do not re-implement staged edits by hand.
347
+
348
+ ##### Customization
349
+
350
+ - **Layout** — `formPlacement` (`start` / `end` / `top` / `bottom`), `stackAt`,
351
+ `formWidth`, `hideForm`, `hideManifest`.
352
+ - **Slots** — `banner` (whole editor), `plateBanner` (plate card only),
353
+ `plateToolbar` (above grid), `plateFooter` (the plate card's footer),
354
+ `footer` (editor-wide action row), `legend` + `legendPlacement`,
355
+ `formExtras`, `formSlot`, `manifestSlot`.
356
+ - **Edit state** — `staged` / `onStagedChange` for a controlled staged record,
357
+ `mergeOnApply` for custom merge semantics, `applyScope="all-plates"` to write
358
+ across every plate at once.
359
+ - **Manifest** — one `manifest` object: `{ filterable, filterColumns, groupable,
360
+ defaultGroupBy, pageSize, pageSizeOptions, enableFillDown }`. Structural bits
361
+ stay top-level: `hideManifest`, `manifestTitle`, `manifestSlot`.
362
+ - **Labels** — one `labels` object covers every string the editor and its
363
+ manifest render, typed as the exported `PlateMapEditorLabels`, so an app's
364
+ translation table is a type error away from going stale:
365
+ `const fr: PlateMapEditorLabels = { … }`. `plateTitle` / `manifestTitle` and
366
+ the import/export menu labels are separate props (they take `ReactNode`, not
367
+ plain text).
368
+ - **Styling** — `className` / `style` on the root, plus one `classNames` map for
369
+ the regions (`PlateMapEditorClassNames`): `{ layout, formCard, plateCard,
370
+ manifestCard, form, grid, manifest }`. Each card also carries
371
+ `data-plate-map-region="form|plate|manifest"`, so plain CSS can target the
372
+ same regions without threading props.
373
+
374
+ ##### Rendering the form outside the editor
375
+
376
+ Hide the built-in form and drive the staged state through the imperative handle.
377
+ The editor keeps owning selection and apply; your form just feeds it.
378
+
379
+ ```tsx
380
+ const editor = React.useRef<PlateMapEditorHandle<MyWell>>(null);
381
+
382
+ <>
383
+ <MySidebarForm
384
+ onChange={(next) => editor.current?.setStaged(next)}
385
+ onApply={() => editor.current?.apply()}
386
+ onClear={() => editor.current?.clear()}
387
+ />
388
+ <PlateMapEditor ref={editor} hideForm {...rest} />
389
+ </>;
390
+ ```
391
+
392
+ ##### Responsiveness
393
+
394
+ The editor responds to **its container's** width, not the viewport's, so it lays
395
+ out correctly inside a narrow panel, split pane, or drawer on a wide screen.
396
+ `stackAt` names a container width — `sm` 640 / `md` 768 (default) / `lg` 1024 /
397
+ `xl` 1280 / `never` — below which the form and grid stack full-width. A plate too
398
+ dense to fit scrolls inside its own container rather than widening the page.
399
+
400
+ ##### Migration notes
401
+
402
+ Everything below is additive; existing code keeps working unchanged.
403
+
404
+ - **Layout now tracks container width, not viewport width.** This is the one
405
+ behavioural change. If your editor is full-width the result is effectively the
406
+ same; if it sits in a narrow panel on a wide screen it will now correctly
407
+ stack instead of rendering a cramped two-column layout. Tune with `stackAt`.
408
+ - `colorForWell` and `emptyEntry` are now **optional** — delete them for
409
+ read-only or single-category views and sensible defaults apply.
410
+ - `className` on the root always worked despite reports otherwise; `style` is
411
+ new.
412
+ - If you previously forked or re-assembled the primitives to change layout,
413
+ replace that with `formPlacement` / `stackAt` / `formWidth` and the slots, or
414
+ with `usePlateMapEditorState` if you still need custom structure. Hand-rolled
415
+ staged/apply logic should be deleted in favour of the hook.
416
+ - If you worked around the hardcoded 360px form column with a width utility,
417
+ switch to `formWidth` — it is the supported path and applies only at and above
418
+ `stackAt`.
419
+ - `manifestFilterable` and `manifestGroupable` still work but are deprecated in
420
+ favour of `manifest={{ filterable, groupable }}`.
421
+
309
422
  ### Charts (`charts/`)
310
423
 
311
424
  Plotly.js-based data visualisations:
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@streamdown/cjk"),r=require("@streamdown/math"),t=require("@streamdown/mermaid"),o=require("./streamdown-code-plugin.cjs"),n={cjk:e.cjk,code:o.streamdownCodePlugin,math:r.math,mermaid:t.mermaid};exports.streamdownPlugins=n;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("@streamdown/cjk"),c=require("./streamdown-code-plugin.cjs");function o(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:()=>e[r]})}}return t.default=e,Object.freeze(t)}async function a(e){try{return await e()}catch{return}}async function u(){const[e,t]=await Promise.all([a(async()=>(await Promise.resolve().then(()=>o(require("@streamdown/math")))).math),a(async()=>(await Promise.resolve().then(()=>o(require("@streamdown/mermaid")))).mermaid)]);return{cjk:i.cjk,code:c.streamdownCodePlugin,...e?{math:e}:{},...t?{mermaid:t}:{}}}exports.getStreamdownPlugins=u;
2
2
  //# sourceMappingURL=streamdown-plugins.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"streamdown-plugins.cjs","sources":["../../../src/components/ai/streamdown-plugins.ts"],"sourcesContent":["/**\n * Full streamdown plugin set for `MessageResponse` / `Reasoning` markdown.\n *\n * This module is only ever reached through `useStreamdownPlugins`'s dynamic\n * import (SW-2007): mermaid, KaTeX, and the shiki grammars behind these\n * plugins land in a lazy chunk instead of the consumer's main bundle. Do not\n * import it statically from component code.\n */\nimport { cjk } from \"@streamdown/cjk\";\nimport { math } from \"@streamdown/math\";\nimport { mermaid } from \"@streamdown/mermaid\";\n\nimport { streamdownCodePlugin } from \"./streamdown-code-plugin\";\n\nimport type { PluginConfig } from \"streamdown\";\n\nexport const streamdownPlugins: PluginConfig = {\n cjk,\n code: streamdownCodePlugin,\n math,\n mermaid,\n};\n"],"names":["streamdownPlugins","cjk","streamdownCodePlugin","math","mermaid"],"mappings":"4NAgBaA,EAAkC,CAAA,IAC7CC,EAAAA,IACA,KAAMC,EAAAA,qBAAA,KACNC,EAAAA,KAAA,QACAC,EAAAA,OACF"}
1
+ {"version":3,"file":"streamdown-plugins.cjs","sources":["../../../src/components/ai/streamdown-plugins.ts"],"sourcesContent":["/**\n * Full streamdown plugin set for `MessageResponse` / `Reasoning` markdown.\n *\n * This module is only ever reached through `useStreamdownPlugins`'s dynamic\n * import (SW-2007): mermaid, KaTeX, and the shiki grammars behind these\n * plugins land in a lazy chunk instead of the consumer's main bundle. Do not\n * import it statically from component code.\n *\n * `@streamdown/math` and `@streamdown/mermaid` are *optional* peer\n * dependencies, so they are resolved with `import()` rather than a static\n * import. A static import forces every consumer that bundles the root barrel\n * to install both — Rollup has to link the named export at build time, and\n * when the package is absent the specifier resolves to an empty\n * `__vite-optional-peer-dep:` stub and the build aborts (#190). Loading them\n * dynamically lets a consumer that omits them degrade at runtime instead:\n * markdown still renders, just without math or mermaid.\n */\nimport { cjk } from \"@streamdown/cjk\";\n\nimport { streamdownCodePlugin } from \"./streamdown-code-plugin\";\n\nimport type { PluginConfig } from \"streamdown\";\n\n/**\n * Resolve one optional peer's plugin export, or `undefined` when the package\n * is not installed. Mirrors how `plotly.js-dist`, `@rdkit/rdkit` and the\n * provider SDKs are loaded elsewhere in the kit.\n */\nasync function optionalPlugin<T>(load: () => Promise<T>): Promise<T | undefined> {\n try {\n return await load();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Build the plugin set, including only the optional plugins that are actually\n * installed. Callers reach this through `useStreamdownPlugins`.\n */\nexport async function getStreamdownPlugins(): Promise<PluginConfig> {\n const [math, mermaid] = await Promise.all([\n optionalPlugin(async () => (await import(\"@streamdown/math\")).math),\n optionalPlugin(async () => (await import(\"@streamdown/mermaid\")).mermaid),\n ]);\n\n return {\n cjk,\n code: streamdownCodePlugin,\n ...(math ? { math } : {}),\n ...(mermaid ? { mermaid } : {}),\n };\n}\n"],"names":["optionalPlugin","load","getStreamdownPlugins","math","mermaid","_interopNamespaceDefault","cjk","streamdownCodePlugin"],"mappings":"0aA4BA,eAAeA,EAAkBC,EAAgD,CAC/E,GAAI,CACF,OAAO,MAAMA,EAAA,CACf,MAAQ,CACN,MACF,CACF,CAMA,eAAsBC,GAA8C,CAClE,KAAM,CAACC,EAAMC,CAAO,EAAI,MAAM,QAAQ,IAAI,CACxCJ,EAAe,UAAa,MAAM,qCAAO,kBAAkB,CAAA,CAAA,GAAG,IAAI,EAClEA,EAAe,UAAa,MAAM,QAAA,QAAA,EAAA,KAAA,IAAAK,EAAA,QAAO,qBAAqB,CAAA,CAAA,GAAG,OAAO,CAAA,CACzE,EAED,MAAO,CAAA,IACLC,EAAAA,IACA,KAAMC,EAAAA,qBACN,GAAIJ,EAAO,CAAE,KAAAA,CAAA,EAAS,CAAA,EACtB,GAAIC,EAAU,CAAE,QAAAA,GAAY,CAAA,CAAC,CAEjC"}
@@ -1,2 +1,6 @@
1
1
  import { PluginConfig } from 'streamdown';
2
- export declare const streamdownPlugins: PluginConfig;
2
+ /**
3
+ * Build the plugin set, including only the optional plugins that are actually
4
+ * installed. Callers reach this through `useStreamdownPlugins`.
5
+ */
6
+ export declare function getStreamdownPlugins(): Promise<PluginConfig>;
@@ -1,14 +1,25 @@
1
- import { cjk as o } from "@streamdown/cjk";
2
- import { math as m } from "@streamdown/math";
3
- import { mermaid as r } from "@streamdown/mermaid";
4
- import { streamdownCodePlugin as t } from "./streamdown-code-plugin.js";
5
- const p = {
6
- cjk: o,
7
- code: t,
8
- math: m,
9
- mermaid: r
10
- };
1
+ import { cjk as i } from "@streamdown/cjk";
2
+ import { streamdownCodePlugin as n } from "./streamdown-code-plugin.js";
3
+ async function r(t) {
4
+ try {
5
+ return await t();
6
+ } catch {
7
+ return;
8
+ }
9
+ }
10
+ async function e() {
11
+ const [t, a] = await Promise.all([
12
+ r(async () => (await import("@streamdown/math")).math),
13
+ r(async () => (await import("@streamdown/mermaid")).mermaid)
14
+ ]);
15
+ return {
16
+ cjk: i,
17
+ code: n,
18
+ ...t ? { math: t } : {},
19
+ ...a ? { mermaid: a } : {}
20
+ };
21
+ }
11
22
  export {
12
- p as streamdownPlugins
23
+ e as getStreamdownPlugins
13
24
  };
14
25
  //# sourceMappingURL=streamdown-plugins.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"streamdown-plugins.js","sources":["../../../src/components/ai/streamdown-plugins.ts"],"sourcesContent":["/**\n * Full streamdown plugin set for `MessageResponse` / `Reasoning` markdown.\n *\n * This module is only ever reached through `useStreamdownPlugins`'s dynamic\n * import (SW-2007): mermaid, KaTeX, and the shiki grammars behind these\n * plugins land in a lazy chunk instead of the consumer's main bundle. Do not\n * import it statically from component code.\n */\nimport { cjk } from \"@streamdown/cjk\";\nimport { math } from \"@streamdown/math\";\nimport { mermaid } from \"@streamdown/mermaid\";\n\nimport { streamdownCodePlugin } from \"./streamdown-code-plugin\";\n\nimport type { PluginConfig } from \"streamdown\";\n\nexport const streamdownPlugins: PluginConfig = {\n cjk,\n code: streamdownCodePlugin,\n math,\n mermaid,\n};\n"],"names":["streamdownPlugins","cjk","streamdownCodePlugin","math","mermaid"],"mappings":";;;;AAgBO,MAAMA,IAAkC;AAAA,EAC7C,KAAAC;AAAA,EACA,MAAMC;AAAA,EACN,MAAAC;AAAA,EACA,SAAAC;AACF;"}
1
+ {"version":3,"file":"streamdown-plugins.js","sources":["../../../src/components/ai/streamdown-plugins.ts"],"sourcesContent":["/**\n * Full streamdown plugin set for `MessageResponse` / `Reasoning` markdown.\n *\n * This module is only ever reached through `useStreamdownPlugins`'s dynamic\n * import (SW-2007): mermaid, KaTeX, and the shiki grammars behind these\n * plugins land in a lazy chunk instead of the consumer's main bundle. Do not\n * import it statically from component code.\n *\n * `@streamdown/math` and `@streamdown/mermaid` are *optional* peer\n * dependencies, so they are resolved with `import()` rather than a static\n * import. A static import forces every consumer that bundles the root barrel\n * to install both — Rollup has to link the named export at build time, and\n * when the package is absent the specifier resolves to an empty\n * `__vite-optional-peer-dep:` stub and the build aborts (#190). Loading them\n * dynamically lets a consumer that omits them degrade at runtime instead:\n * markdown still renders, just without math or mermaid.\n */\nimport { cjk } from \"@streamdown/cjk\";\n\nimport { streamdownCodePlugin } from \"./streamdown-code-plugin\";\n\nimport type { PluginConfig } from \"streamdown\";\n\n/**\n * Resolve one optional peer's plugin export, or `undefined` when the package\n * is not installed. Mirrors how `plotly.js-dist`, `@rdkit/rdkit` and the\n * provider SDKs are loaded elsewhere in the kit.\n */\nasync function optionalPlugin<T>(load: () => Promise<T>): Promise<T | undefined> {\n try {\n return await load();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Build the plugin set, including only the optional plugins that are actually\n * installed. Callers reach this through `useStreamdownPlugins`.\n */\nexport async function getStreamdownPlugins(): Promise<PluginConfig> {\n const [math, mermaid] = await Promise.all([\n optionalPlugin(async () => (await import(\"@streamdown/math\")).math),\n optionalPlugin(async () => (await import(\"@streamdown/mermaid\")).mermaid),\n ]);\n\n return {\n cjk,\n code: streamdownCodePlugin,\n ...(math ? { math } : {}),\n ...(mermaid ? { mermaid } : {}),\n };\n}\n"],"names":["optionalPlugin","load","getStreamdownPlugins","math","mermaid","cjk","streamdownCodePlugin"],"mappings":";;AA4BA,eAAeA,EAAkBC,GAAgD;AAC/E,MAAI;AACF,WAAO,MAAMA,EAAA;AAAA,EACf,QAAQ;AACN;AAAA,EACF;AACF;AAMA,eAAsBC,IAA8C;AAClE,QAAM,CAACC,GAAMC,CAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,IACxCJ,EAAe,aAAa,MAAM,OAAO,kBAAkB,GAAG,IAAI;AAAA,IAClEA,EAAe,aAAa,MAAM,OAAO,qBAAqB,GAAG,OAAO;AAAA,EAAA,CACzE;AAED,SAAO;AAAA,IACL,KAAAK;AAAA,IACA,MAAMC;AAAA,IACN,GAAIH,IAAO,EAAE,MAAAA,EAAA,IAAS,CAAA;AAAA,IACtB,GAAIC,IAAU,EAAE,SAAAA,MAAY,CAAA;AAAA,EAAC;AAEjC;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react");let n=null,t=null;function i(){return t??=Promise.resolve().then(()=>require("./streamdown-plugins.cjs")).then(e=>(n=e.streamdownPlugins,n)).catch(e=>{throw t=null,n=null,e}),t}function o(){const[e,r]=l.useState(n??void 0);return l.useEffect(()=>{if(e)return;let u=!1;return i().then(s=>{u||r(s)}),()=>{u=!0}},[e]),e}exports.useStreamdownPlugins=o;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react");let n=null,t=null;function s(){return t??=Promise.resolve().then(()=>require("./streamdown-plugins.cjs")).then(e=>e.getStreamdownPlugins()).then(e=>(n=e,e)).catch(e=>{throw t=null,n=null,e}),t}function o(){const[e,l]=r.useState(n??void 0);return r.useEffect(()=>{if(e)return;let u=!1;return s().then(i=>{u||l(i)}),()=>{u=!0}},[e]),e}exports.useStreamdownPlugins=o;
2
2
  //# sourceMappingURL=use-streamdown-plugins.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-streamdown-plugins.cjs","sources":["../../../src/components/ai/use-streamdown-plugins.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport type { PluginConfig } from \"streamdown\";\n\n// Module-level cache so the lazy chunk is fetched once and later mounts get\n// the plugins synchronously on first render (no highlight flash).\nlet cachedPlugins: PluginConfig | null = null;\nlet pluginsPromise: Promise<PluginConfig> | null = null;\n\nfunction loadStreamdownPlugins(): Promise<PluginConfig> {\n pluginsPromise ??= import(\"./streamdown-plugins\")\n .then((mod) => {\n cachedPlugins = mod.streamdownPlugins;\n return cachedPlugins;\n })\n .catch((error) => {\n pluginsPromise = null;\n cachedPlugins = null;\n throw error;\n });\n return pluginsPromise;\n}\n\n/**\n * Lazily loads the streamdown plugin set (SW-2007). Markdown renders\n * immediately without plugins; code highlighting, math, and mermaid upgrade\n * in place once the lazy chunk arrives, keeping shiki/KaTeX/mermaid out of\n * the consumer's main bundle.\n */\nexport function useStreamdownPlugins(): PluginConfig | undefined {\n const [plugins, setPlugins] = useState<PluginConfig | undefined>(\n cachedPlugins ?? undefined,\n );\n\n useEffect(() => {\n if (plugins) return;\n let cancelled = false;\n void loadStreamdownPlugins().then((loaded) => {\n if (!cancelled) setPlugins(loaded);\n });\n return () => {\n cancelled = true;\n };\n }, [plugins]);\n\n return plugins;\n}\n"],"names":["cachedPlugins","pluginsPromise","loadStreamdownPlugins","mod","error","useStreamdownPlugins","plugins","setPlugins","useState","useEffect","cancelled","loaded"],"mappings":"yGAMA,IAAIA,EAAqC,KACrCC,EAA+C,KAEnD,SAASC,GAA+C,CACtD,OAAAD,IAAmB,QAAA,QAAA,EAAA,KAAA,IAAA,QAAO,0BAAsB,CAAA,EAC7C,KAAME,IACLH,EAAgBG,EAAI,kBACbH,EACR,EACA,MAAOI,GAAU,CAChB,MAAAH,EAAiB,KACjBD,EAAgB,KACVI,CACR,CAAC,EACIH,CACT,CAQO,SAASI,GAAiD,CAC/D,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAC5BR,GAAiB,MAAA,EAGnBS,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAIH,EAAS,OACb,IAAII,EAAY,GAChB,OAAKR,EAAA,EAAwB,KAAMS,GAAW,CACvCD,GAAWH,EAAWI,CAAM,CACnC,CAAC,EACM,IAAM,CACXD,EAAY,EACd,CACF,EAAG,CAACJ,CAAO,CAAC,EAELA,CACT"}
1
+ {"version":3,"file":"use-streamdown-plugins.cjs","sources":["../../../src/components/ai/use-streamdown-plugins.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport type { PluginConfig } from \"streamdown\";\n\n// Module-level cache so the lazy chunk is fetched once and later mounts get\n// the plugins synchronously on first render (no highlight flash).\nlet cachedPlugins: PluginConfig | null = null;\nlet pluginsPromise: Promise<PluginConfig> | null = null;\n\nfunction loadStreamdownPlugins(): Promise<PluginConfig> {\n pluginsPromise ??= import(\"./streamdown-plugins\")\n .then((mod) => mod.getStreamdownPlugins())\n .then((plugins) => {\n cachedPlugins = plugins;\n return plugins;\n })\n .catch((error) => {\n pluginsPromise = null;\n cachedPlugins = null;\n throw error;\n });\n return pluginsPromise;\n}\n\n/**\n * Lazily loads the streamdown plugin set (SW-2007). Markdown renders\n * immediately without plugins; code highlighting, math, and mermaid upgrade\n * in place once the lazy chunk arrives, keeping shiki/KaTeX/mermaid out of\n * the consumer's main bundle.\n */\nexport function useStreamdownPlugins(): PluginConfig | undefined {\n const [plugins, setPlugins] = useState<PluginConfig | undefined>(\n cachedPlugins ?? undefined,\n );\n\n useEffect(() => {\n if (plugins) return;\n let cancelled = false;\n void loadStreamdownPlugins().then((loaded) => {\n if (!cancelled) setPlugins(loaded);\n });\n return () => {\n cancelled = true;\n };\n }, [plugins]);\n\n return plugins;\n}\n"],"names":["cachedPlugins","pluginsPromise","loadStreamdownPlugins","mod","plugins","error","useStreamdownPlugins","setPlugins","useState","useEffect","cancelled","loaded"],"mappings":"yGAMA,IAAIA,EAAqC,KACrCC,EAA+C,KAEnD,SAASC,GAA+C,CACtD,OAAAD,IAAmB,QAAA,QAAA,EAAA,KAAA,IAAA,QAAO,0BAAsB,GAC7C,KAAME,GAAQA,EAAI,qBAAA,CAAsB,EACxC,KAAMC,IACLJ,EAAgBI,EACTA,EACR,EACA,MAAOC,GAAU,CAChB,MAAAJ,EAAiB,KACjBD,EAAgB,KACVK,CACR,CAAC,EACIJ,CACT,CAQO,SAASK,GAAiD,CAC/D,KAAM,CAACF,EAASG,CAAU,EAAIC,EAAAA,SAC5BR,GAAiB,MAAA,EAGnBS,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAIL,EAAS,OACb,IAAIM,EAAY,GAChB,OAAKR,EAAA,EAAwB,KAAMS,GAAW,CACvCD,GAAWH,EAAWI,CAAM,CACnC,CAAC,EACM,IAAM,CACXD,EAAY,EACd,CACF,EAAG,CAACN,CAAO,CAAC,EAELA,CACT"}
@@ -1,23 +1,23 @@
1
1
  import { useState as i, useEffect as o } from "react";
2
- let e = null, t = null;
2
+ let n = null, t = null;
3
3
  function s() {
4
- return t ??= import("./streamdown-plugins.js").then((n) => (e = n.streamdownPlugins, e)).catch((n) => {
5
- throw t = null, e = null, n;
4
+ return t ??= import("./streamdown-plugins.js").then((e) => e.getStreamdownPlugins()).then((e) => (n = e, e)).catch((e) => {
5
+ throw t = null, n = null, e;
6
6
  }), t;
7
7
  }
8
8
  function a() {
9
- const [n, u] = i(
10
- e ?? void 0
9
+ const [e, u] = i(
10
+ n ?? void 0
11
11
  );
12
12
  return o(() => {
13
- if (n) return;
13
+ if (e) return;
14
14
  let l = !1;
15
15
  return s().then((r) => {
16
16
  l || u(r);
17
17
  }), () => {
18
18
  l = !0;
19
19
  };
20
- }, [n]), n;
20
+ }, [e]), e;
21
21
  }
22
22
  export {
23
23
  a as useStreamdownPlugins
@@ -1 +1 @@
1
- {"version":3,"file":"use-streamdown-plugins.js","sources":["../../../src/components/ai/use-streamdown-plugins.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport type { PluginConfig } from \"streamdown\";\n\n// Module-level cache so the lazy chunk is fetched once and later mounts get\n// the plugins synchronously on first render (no highlight flash).\nlet cachedPlugins: PluginConfig | null = null;\nlet pluginsPromise: Promise<PluginConfig> | null = null;\n\nfunction loadStreamdownPlugins(): Promise<PluginConfig> {\n pluginsPromise ??= import(\"./streamdown-plugins\")\n .then((mod) => {\n cachedPlugins = mod.streamdownPlugins;\n return cachedPlugins;\n })\n .catch((error) => {\n pluginsPromise = null;\n cachedPlugins = null;\n throw error;\n });\n return pluginsPromise;\n}\n\n/**\n * Lazily loads the streamdown plugin set (SW-2007). Markdown renders\n * immediately without plugins; code highlighting, math, and mermaid upgrade\n * in place once the lazy chunk arrives, keeping shiki/KaTeX/mermaid out of\n * the consumer's main bundle.\n */\nexport function useStreamdownPlugins(): PluginConfig | undefined {\n const [plugins, setPlugins] = useState<PluginConfig | undefined>(\n cachedPlugins ?? undefined,\n );\n\n useEffect(() => {\n if (plugins) return;\n let cancelled = false;\n void loadStreamdownPlugins().then((loaded) => {\n if (!cancelled) setPlugins(loaded);\n });\n return () => {\n cancelled = true;\n };\n }, [plugins]);\n\n return plugins;\n}\n"],"names":["cachedPlugins","pluginsPromise","loadStreamdownPlugins","mod","error","useStreamdownPlugins","plugins","setPlugins","useState","useEffect","cancelled","loaded"],"mappings":";AAMA,IAAIA,IAAqC,MACrCC,IAA+C;AAEnD,SAASC,IAA+C;AACtD,SAAAD,MAAmB,OAAO,yBAAsB,EAC7C,KAAK,CAACE,OACLH,IAAgBG,EAAI,mBACbH,EACR,EACA,MAAM,CAACI,MAAU;AAChB,UAAAH,IAAiB,MACjBD,IAAgB,MACVI;AAAA,EACR,CAAC,GACIH;AACT;AAQO,SAASI,IAAiD;AAC/D,QAAM,CAACC,GAASC,CAAU,IAAIC;AAAA,IAC5BR,KAAiB;AAAA,EAAA;AAGnB,SAAAS,EAAU,MAAM;AACd,QAAIH,EAAS;AACb,QAAII,IAAY;AAChB,WAAKR,EAAA,EAAwB,KAAK,CAACS,MAAW;AAC5C,MAAKD,KAAWH,EAAWI,CAAM;AAAA,IACnC,CAAC,GACM,MAAM;AACX,MAAAD,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACJ,CAAO,CAAC,GAELA;AACT;"}
1
+ {"version":3,"file":"use-streamdown-plugins.js","sources":["../../../src/components/ai/use-streamdown-plugins.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport type { PluginConfig } from \"streamdown\";\n\n// Module-level cache so the lazy chunk is fetched once and later mounts get\n// the plugins synchronously on first render (no highlight flash).\nlet cachedPlugins: PluginConfig | null = null;\nlet pluginsPromise: Promise<PluginConfig> | null = null;\n\nfunction loadStreamdownPlugins(): Promise<PluginConfig> {\n pluginsPromise ??= import(\"./streamdown-plugins\")\n .then((mod) => mod.getStreamdownPlugins())\n .then((plugins) => {\n cachedPlugins = plugins;\n return plugins;\n })\n .catch((error) => {\n pluginsPromise = null;\n cachedPlugins = null;\n throw error;\n });\n return pluginsPromise;\n}\n\n/**\n * Lazily loads the streamdown plugin set (SW-2007). Markdown renders\n * immediately without plugins; code highlighting, math, and mermaid upgrade\n * in place once the lazy chunk arrives, keeping shiki/KaTeX/mermaid out of\n * the consumer's main bundle.\n */\nexport function useStreamdownPlugins(): PluginConfig | undefined {\n const [plugins, setPlugins] = useState<PluginConfig | undefined>(\n cachedPlugins ?? undefined,\n );\n\n useEffect(() => {\n if (plugins) return;\n let cancelled = false;\n void loadStreamdownPlugins().then((loaded) => {\n if (!cancelled) setPlugins(loaded);\n });\n return () => {\n cancelled = true;\n };\n }, [plugins]);\n\n return plugins;\n}\n"],"names":["cachedPlugins","pluginsPromise","loadStreamdownPlugins","mod","plugins","error","useStreamdownPlugins","setPlugins","useState","useEffect","cancelled","loaded"],"mappings":";AAMA,IAAIA,IAAqC,MACrCC,IAA+C;AAEnD,SAASC,IAA+C;AACtD,SAAAD,MAAmB,OAAO,yBAAsB,EAC7C,KAAK,CAACE,MAAQA,EAAI,qBAAA,CAAsB,EACxC,KAAK,CAACC,OACLJ,IAAgBI,GACTA,EACR,EACA,MAAM,CAACC,MAAU;AAChB,UAAAJ,IAAiB,MACjBD,IAAgB,MACVK;AAAA,EACR,CAAC,GACIJ;AACT;AAQO,SAASK,IAAiD;AAC/D,QAAM,CAACF,GAASG,CAAU,IAAIC;AAAA,IAC5BR,KAAiB;AAAA,EAAA;AAGnB,SAAAS,EAAU,MAAM;AACd,QAAIL,EAAS;AACb,QAAIM,IAAY;AAChB,WAAKR,EAAA,EAAwB,KAAK,CAACS,MAAW;AAC5C,MAAKD,KAAWH,EAAWI,CAAM;AAAA,IACnC,CAAC,GACM,MAAM;AACX,MAAAD,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACN,CAAO,CAAC,GAELA;AACT;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),x=require("lucide-react"),u=require("../../../ui/button.cjs"),w=require("../../../ui/input.cjs"),h=require("../../../ui/popover.cjs"),l=require("../../../ui/select.cjs"),z=require("../../../lib/utils.cjs"),F={contains:"contains",equals:"equals",not_equals:"not equals",starts_with:"starts with",ends_with:"ends with",is_empty:"is empty",is_not_empty:"is not empty"},P=["is_empty","is_not_empty"],f=["contains","equals","not_equals","starts_with","ends_with","is_empty","is_not_empty"];function R(n,d){const a=d?.[0]??"contains";return{id:crypto.randomUUID(),columnId:n,operator:a,value:""}}function O({columns:n,columnLabel:d,filters:a,onFiltersChange:i,triggerLabel:m="Filter",className:g}){const _=t=>d?.(t)??t,v=n[0],y=v?.columnId??"",C=()=>i([...a,R(y,v?.operators)]),I=t=>i(a.filter(c=>c.id!==t)),p=(t,c)=>i(a.map(r=>r.id===t?{...r,...c}:r)),N=()=>i([]),o=a.length;return e.jsxs(h.Popover,{children:[e.jsx(h.PopoverTrigger,{asChild:!0,children:e.jsxs(u.Button,{type:"button",variant:"outline",size:"sm","data-slot":"manifest-filter",className:z.cn(g),"aria-label":o>0?`${m} (${o} active)`:m,children:[e.jsx(x.ListFilterIcon,{className:"size-3.5"}),m,o>0?e.jsx("span",{className:"flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground",children:o}):null]})}),e.jsx(h.PopoverContent,{align:"end",className:"min-w-80","aria-label":"Filter conditions",children:e.jsxs("div",{className:"flex flex-col gap-2",children:[a.map(t=>{const r=n.find(s=>s.columnId===t.columnId)?.operators??f,S=P.includes(t.operator);return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(l.Select,{value:t.columnId,onValueChange:s=>{const j=n.find(q=>q.columnId===s)?.operators??f,b=j.includes(t.operator)?t.operator:j[0]??"contains";p(t.id,{columnId:s,operator:b,value:""})},children:[e.jsx(l.SelectTrigger,{"aria-label":"Filter column",size:"sm",className:"w-36",children:e.jsx(l.SelectValue,{})}),e.jsx(l.SelectContent,{children:n.map(s=>e.jsx(l.SelectItem,{value:s.columnId,children:s.label??_(s.columnId)},s.columnId))})]}),e.jsxs(l.Select,{value:t.operator,onValueChange:s=>p(t.id,{operator:s,value:""}),children:[e.jsx(l.SelectTrigger,{"aria-label":"Filter operator",size:"sm",className:"w-32",children:e.jsx(l.SelectValue,{})}),e.jsx(l.SelectContent,{children:r.map(s=>e.jsx(l.SelectItem,{value:s,children:F[s]},s))})]}),S?e.jsx("div",{className:"h-8 w-40","aria-hidden":!0}):e.jsx(w.Input,{className:"w-40",placeholder:"Value…",value:t.value,onChange:s=>p(t.id,{value:s.target.value})}),e.jsx(u.Button,{type:"button",variant:"ghost",size:"icon",className:"size-8 shrink-0 text-muted-foreground hover:text-foreground",onClick:()=>I(t.id),"aria-label":"Remove filter",children:e.jsx(x.XIcon,{className:"size-3.5"})})]},t.id)}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(u.Button,{type:"button",variant:"outline",size:"sm",onClick:C,disabled:n.length===0,children:[e.jsx(x.PlusIcon,{className:"size-3.5"}),"Add filter"]}),a.length>0?e.jsx(u.Button,{type:"button",variant:"ghost",size:"sm",className:"text-muted-foreground",onClick:N,children:"Clear all"}):null]})]})})]})}exports.ManifestFilterPopover=O;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),x=require("lucide-react"),u=require("../../../ui/button.cjs"),F=require("../../../ui/input.cjs"),h=require("../../../ui/popover.cjs"),l=require("../../../ui/select.cjs"),P=require("../../../lib/utils.cjs"),R={contains:"contains",equals:"equals",not_equals:"not equals",starts_with:"starts with",ends_with:"ends with",is_empty:"is empty",is_not_empty:"is not empty"},O=["is_empty","is_not_empty"],f=["contains","equals","not_equals","starts_with","ends_with","is_empty","is_not_empty"];function A(n,d){const a=d?.[0]??"contains";return{id:crypto.randomUUID(),columnId:n,operator:a,value:""}}function E({columns:n,columnLabel:d,filters:a,onFiltersChange:i,triggerLabel:m="Filter",valuePlaceholder:g="Value…",clearAllLabel:_="Clear all",className:y}){const C=t=>d?.(t)??t,v=n[0],I=v?.columnId??"",N=()=>i([...a,A(I,v?.operators)]),S=t=>i(a.filter(c=>c.id!==t)),p=(t,c)=>i(a.map(r=>r.id===t?{...r,...c}:r)),b=()=>i([]),o=a.length;return e.jsxs(h.Popover,{children:[e.jsx(h.PopoverTrigger,{asChild:!0,children:e.jsxs(u.Button,{type:"button",variant:"outline",size:"sm","data-slot":"manifest-filter",className:P.cn(y),"aria-label":o>0?`${m} (${o} active)`:m,children:[e.jsx(x.ListFilterIcon,{className:"size-3.5"}),m,o>0?e.jsx("span",{className:"flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground",children:o}):null]})}),e.jsx(h.PopoverContent,{align:"end",className:"min-w-80","aria-label":"Filter conditions",children:e.jsxs("div",{className:"flex flex-col gap-2",children:[a.map(t=>{const r=n.find(s=>s.columnId===t.columnId)?.operators??f,q=O.includes(t.operator);return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(l.Select,{value:t.columnId,onValueChange:s=>{const j=n.find(z=>z.columnId===s)?.operators??f,w=j.includes(t.operator)?t.operator:j[0]??"contains";p(t.id,{columnId:s,operator:w,value:""})},children:[e.jsx(l.SelectTrigger,{"aria-label":"Filter column",size:"sm",className:"w-36",children:e.jsx(l.SelectValue,{})}),e.jsx(l.SelectContent,{children:n.map(s=>e.jsx(l.SelectItem,{value:s.columnId,children:s.label??C(s.columnId)},s.columnId))})]}),e.jsxs(l.Select,{value:t.operator,onValueChange:s=>p(t.id,{operator:s,value:""}),children:[e.jsx(l.SelectTrigger,{"aria-label":"Filter operator",size:"sm",className:"w-32",children:e.jsx(l.SelectValue,{})}),e.jsx(l.SelectContent,{children:r.map(s=>e.jsx(l.SelectItem,{value:s,children:R[s]},s))})]}),q?e.jsx("div",{className:"h-8 w-40","aria-hidden":!0}):e.jsx(F.Input,{className:"w-40",placeholder:g,value:t.value,onChange:s=>p(t.id,{value:s.target.value})}),e.jsx(u.Button,{type:"button",variant:"ghost",size:"icon",className:"size-8 shrink-0 text-muted-foreground hover:text-foreground",onClick:()=>S(t.id),"aria-label":"Remove filter",children:e.jsx(x.XIcon,{className:"size-3.5"})})]},t.id)}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(u.Button,{type:"button",variant:"outline",size:"sm",onClick:N,disabled:n.length===0,children:[e.jsx(x.PlusIcon,{className:"size-3.5"}),"Add filter"]}),a.length>0?e.jsx(u.Button,{type:"button",variant:"ghost",size:"sm",className:"text-muted-foreground",onClick:b,children:_}):null]})]})})]})}exports.ManifestFilterPopover=E;
2
2
  //# sourceMappingURL=ManifestFilterPopover.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ManifestFilterPopover.cjs","sources":["../../../../src/components/composed/PlateMapEditor/ManifestFilterPopover.tsx"],"sourcesContent":["import { ListFilterIcon, PlusIcon, XIcon } from \"lucide-react\";\n\nimport type { FilterColumnConfig, FilterCondition, FilterOperator } from \"@/components/ui/data-table/data-table\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\nimport { cn } from \"@/lib/utils\";\n\nconst OPERATOR_LABELS: Record<FilterOperator, string> = {\n contains: \"contains\",\n equals: \"equals\",\n not_equals: \"not equals\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n is_empty: \"is empty\",\n is_not_empty: \"is not empty\",\n};\n\nconst VALUE_FREE_OPERATORS: FilterOperator[] = [\"is_empty\", \"is_not_empty\"];\n\nconst DEFAULT_OPERATORS: FilterOperator[] = [\n \"contains\",\n \"equals\",\n \"not_equals\",\n \"starts_with\",\n \"ends_with\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nfunction makeCondition(columnId: string, allowedOperators?: FilterOperator[]): FilterCondition {\n const operator = allowedOperators?.[0] ?? \"contains\";\n return { id: crypto.randomUUID(), columnId, operator, value: \"\" };\n}\n\nexport interface ManifestFilterPopoverProps {\n /** Filterable columns. Operator subsets can be specified per column. */\n columns: FilterColumnConfig[];\n /** Column id → display label resolver. */\n columnLabel?: (columnId: string) => string;\n filters: FilterCondition[];\n onFiltersChange: (next: FilterCondition[]) => void;\n triggerLabel?: string;\n className?: string;\n}\n\nexport function ManifestFilterPopover({\n columns,\n columnLabel,\n filters,\n onFiltersChange,\n triggerLabel = \"Filter\",\n className,\n}: ManifestFilterPopoverProps) {\n const labelFor = (columnId: string): string => columnLabel?.(columnId) ?? columnId;\n const firstColumn = columns[0];\n const firstColumnId = firstColumn?.columnId ?? \"\";\n\n const addFilter = () => onFiltersChange([...filters, makeCondition(firstColumnId, firstColumn?.operators)]);\n const removeFilter = (id: string) => onFiltersChange(filters.filter((cond) => cond.id !== id));\n const updateFilter = (id: string, patch: Partial<FilterCondition>) =>\n onFiltersChange(filters.map((cond) => (cond.id === id ? { ...cond, ...patch } : cond)));\n const clearAll = () => onFiltersChange([]);\n\n const activeCount = filters.length;\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n data-slot=\"manifest-filter\"\n className={cn(className)}\n aria-label={activeCount > 0 ? `${triggerLabel} (${activeCount} active)` : triggerLabel}\n >\n <ListFilterIcon className=\"size-3.5\" />\n {triggerLabel}\n {activeCount > 0 ? (\n <span className=\"flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground\">\n {activeCount}\n </span>\n ) : null}\n </Button>\n </PopoverTrigger>\n\n <PopoverContent align=\"end\" className=\"min-w-80\" aria-label=\"Filter conditions\">\n <div className=\"flex flex-col gap-2\">\n {filters.map((condition) => {\n const colConfig = columns.find((c) => c.columnId === condition.columnId);\n const operators = colConfig?.operators ?? DEFAULT_OPERATORS;\n const isValueFree = VALUE_FREE_OPERATORS.includes(condition.operator);\n return (\n <div key={condition.id} className=\"flex items-center gap-2\">\n <Select\n value={condition.columnId}\n onValueChange={(value) => {\n const nextConfig = columns.find((c) => c.columnId === value);\n const nextOperators = nextConfig?.operators ?? DEFAULT_OPERATORS;\n const nextOperator = nextOperators.includes(condition.operator)\n ? condition.operator\n : (nextOperators[0] ?? \"contains\");\n updateFilter(condition.id, { columnId: value, operator: nextOperator, value: \"\" });\n }}\n >\n <SelectTrigger aria-label=\"Filter column\" size=\"sm\" className=\"w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {columns.map((c) => (\n <SelectItem key={c.columnId} value={c.columnId}>\n {c.label ?? labelFor(c.columnId)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Select\n value={condition.operator}\n onValueChange={(value) =>\n updateFilter(condition.id, { operator: value as FilterOperator, value: \"\" })\n }\n >\n <SelectTrigger aria-label=\"Filter operator\" size=\"sm\" className=\"w-32\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {operators.map((op) => (\n <SelectItem key={op} value={op}>\n {OPERATOR_LABELS[op]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {isValueFree ? (\n <div className=\"h-8 w-40\" aria-hidden />\n ) : (\n <Input\n className=\"w-40\"\n placeholder=\"Value…\"\n value={condition.value}\n onChange={(event) => updateFilter(condition.id, { value: event.target.value })}\n />\n )}\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8 shrink-0 text-muted-foreground hover:text-foreground\"\n onClick={() => removeFilter(condition.id)}\n aria-label=\"Remove filter\"\n >\n <XIcon className=\"size-3.5\" />\n </Button>\n </div>\n );\n })}\n\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={addFilter}\n disabled={columns.length === 0}\n >\n <PlusIcon className=\"size-3.5\" />\n Add filter\n </Button>\n {filters.length > 0 ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground\"\n onClick={clearAll}\n >\n Clear all\n </Button>\n ) : null}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"],"names":["OPERATOR_LABELS","VALUE_FREE_OPERATORS","DEFAULT_OPERATORS","makeCondition","columnId","allowedOperators","operator","ManifestFilterPopover","columns","columnLabel","filters","onFiltersChange","triggerLabel","className","labelFor","firstColumn","firstColumnId","addFilter","removeFilter","id","cond","updateFilter","patch","clearAll","activeCount","Popover","jsx","PopoverTrigger","jsxs","Button","cn","ListFilterIcon","PopoverContent","condition","operators","c","isValueFree","Select","value","nextOperators","nextOperator","SelectTrigger","SelectValue","SelectContent","SelectItem","op","Input","event","XIcon","PlusIcon"],"mappings":"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"}
1
+ {"version":3,"file":"ManifestFilterPopover.cjs","sources":["../../../../src/components/composed/PlateMapEditor/ManifestFilterPopover.tsx"],"sourcesContent":["import { ListFilterIcon, PlusIcon, XIcon } from \"lucide-react\";\n\nimport type { FilterColumnConfig, FilterCondition, FilterOperator } from \"@/components/ui/data-table/data-table\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\nimport { cn } from \"@/lib/utils\";\n\nconst OPERATOR_LABELS: Record<FilterOperator, string> = {\n contains: \"contains\",\n equals: \"equals\",\n not_equals: \"not equals\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n is_empty: \"is empty\",\n is_not_empty: \"is not empty\",\n};\n\nconst VALUE_FREE_OPERATORS: FilterOperator[] = [\"is_empty\", \"is_not_empty\"];\n\nconst DEFAULT_OPERATORS: FilterOperator[] = [\n \"contains\",\n \"equals\",\n \"not_equals\",\n \"starts_with\",\n \"ends_with\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nfunction makeCondition(columnId: string, allowedOperators?: FilterOperator[]): FilterCondition {\n const operator = allowedOperators?.[0] ?? \"contains\";\n return { id: crypto.randomUUID(), columnId, operator, value: \"\" };\n}\n\nexport interface ManifestFilterPopoverProps {\n /** Filterable columns. Operator subsets can be specified per column. */\n columns: FilterColumnConfig[];\n /** Column id → display label resolver. */\n columnLabel?: (columnId: string) => string;\n filters: FilterCondition[];\n onFiltersChange: (next: FilterCondition[]) => void;\n triggerLabel?: string;\n /** Placeholder for a condition's value input. Defaults to `\"Value…\"`. */\n valuePlaceholder?: string;\n /** Label for the clear-every-filter button. Defaults to `\"Clear all\"`. */\n clearAllLabel?: string;\n className?: string;\n}\n\nexport function ManifestFilterPopover({\n columns,\n columnLabel,\n filters,\n onFiltersChange,\n triggerLabel = \"Filter\",\n valuePlaceholder = \"Value…\",\n clearAllLabel = \"Clear all\",\n className,\n}: ManifestFilterPopoverProps) {\n const labelFor = (columnId: string): string => columnLabel?.(columnId) ?? columnId;\n const firstColumn = columns[0];\n const firstColumnId = firstColumn?.columnId ?? \"\";\n\n const addFilter = () => onFiltersChange([...filters, makeCondition(firstColumnId, firstColumn?.operators)]);\n const removeFilter = (id: string) => onFiltersChange(filters.filter((cond) => cond.id !== id));\n const updateFilter = (id: string, patch: Partial<FilterCondition>) =>\n onFiltersChange(filters.map((cond) => (cond.id === id ? { ...cond, ...patch } : cond)));\n const clearAll = () => onFiltersChange([]);\n\n const activeCount = filters.length;\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n data-slot=\"manifest-filter\"\n className={cn(className)}\n aria-label={activeCount > 0 ? `${triggerLabel} (${activeCount} active)` : triggerLabel}\n >\n <ListFilterIcon className=\"size-3.5\" />\n {triggerLabel}\n {activeCount > 0 ? (\n <span className=\"flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground\">\n {activeCount}\n </span>\n ) : null}\n </Button>\n </PopoverTrigger>\n\n <PopoverContent align=\"end\" className=\"min-w-80\" aria-label=\"Filter conditions\">\n <div className=\"flex flex-col gap-2\">\n {filters.map((condition) => {\n const colConfig = columns.find((c) => c.columnId === condition.columnId);\n const operators = colConfig?.operators ?? DEFAULT_OPERATORS;\n const isValueFree = VALUE_FREE_OPERATORS.includes(condition.operator);\n return (\n <div key={condition.id} className=\"flex items-center gap-2\">\n <Select\n value={condition.columnId}\n onValueChange={(value) => {\n const nextConfig = columns.find((c) => c.columnId === value);\n const nextOperators = nextConfig?.operators ?? DEFAULT_OPERATORS;\n const nextOperator = nextOperators.includes(condition.operator)\n ? condition.operator\n : (nextOperators[0] ?? \"contains\");\n updateFilter(condition.id, { columnId: value, operator: nextOperator, value: \"\" });\n }}\n >\n <SelectTrigger aria-label=\"Filter column\" size=\"sm\" className=\"w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {columns.map((c) => (\n <SelectItem key={c.columnId} value={c.columnId}>\n {c.label ?? labelFor(c.columnId)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Select\n value={condition.operator}\n onValueChange={(value) =>\n updateFilter(condition.id, { operator: value as FilterOperator, value: \"\" })\n }\n >\n <SelectTrigger aria-label=\"Filter operator\" size=\"sm\" className=\"w-32\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {operators.map((op) => (\n <SelectItem key={op} value={op}>\n {OPERATOR_LABELS[op]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {isValueFree ? (\n <div className=\"h-8 w-40\" aria-hidden />\n ) : (\n <Input\n className=\"w-40\"\n placeholder={valuePlaceholder}\n value={condition.value}\n onChange={(event) => updateFilter(condition.id, { value: event.target.value })}\n />\n )}\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8 shrink-0 text-muted-foreground hover:text-foreground\"\n onClick={() => removeFilter(condition.id)}\n aria-label=\"Remove filter\"\n >\n <XIcon className=\"size-3.5\" />\n </Button>\n </div>\n );\n })}\n\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={addFilter}\n disabled={columns.length === 0}\n >\n <PlusIcon className=\"size-3.5\" />\n Add filter\n </Button>\n {filters.length > 0 ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground\"\n onClick={clearAll}\n >\n {clearAllLabel}\n </Button>\n ) : null}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"],"names":["OPERATOR_LABELS","VALUE_FREE_OPERATORS","DEFAULT_OPERATORS","makeCondition","columnId","allowedOperators","operator","ManifestFilterPopover","columns","columnLabel","filters","onFiltersChange","triggerLabel","valuePlaceholder","clearAllLabel","className","labelFor","firstColumn","firstColumnId","addFilter","removeFilter","id","cond","updateFilter","patch","clearAll","activeCount","Popover","jsx","PopoverTrigger","jsxs","Button","cn","ListFilterIcon","PopoverContent","condition","operators","c","isValueFree","Select","value","nextOperators","nextOperator","SelectTrigger","SelectValue","SelectContent","SelectItem","op","Input","event","XIcon","PlusIcon"],"mappings":"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"}
@@ -7,6 +7,10 @@ export interface ManifestFilterPopoverProps {
7
7
  filters: FilterCondition[];
8
8
  onFiltersChange: (next: FilterCondition[]) => void;
9
9
  triggerLabel?: string;
10
+ /** Placeholder for a condition's value input. Defaults to `"Value…"`. */
11
+ valuePlaceholder?: string;
12
+ /** Label for the clear-every-filter button. Defaults to `"Clear all"`. */
13
+ clearAllLabel?: string;
10
14
  className?: string;
11
15
  }
12
- export declare function ManifestFilterPopover({ columns, columnLabel, filters, onFiltersChange, triggerLabel, className, }: ManifestFilterPopoverProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function ManifestFilterPopover({ columns, columnLabel, filters, onFiltersChange, triggerLabel, valuePlaceholder, clearAllLabel, className, }: ManifestFilterPopoverProps): import("react/jsx-runtime").JSX.Element;
@@ -1,11 +1,11 @@
1
1
  import { jsxs as l, jsx as t } from "react/jsx-runtime";
2
- import { ListFilterIcon as P, XIcon as R, PlusIcon as S } from "lucide-react";
2
+ import { ListFilterIcon as S, XIcon as q, PlusIcon as T } from "lucide-react";
3
3
  import { Button as m } from "../../../ui/button.js";
4
- import { Input as q } from "../../../ui/input.js";
5
- import { Popover as T, PopoverTrigger as V, PopoverContent as k } from "../../../ui/popover.js";
4
+ import { Input as V } from "../../../ui/input.js";
5
+ import { Popover as k, PopoverTrigger as U, PopoverContent as j } from "../../../ui/popover.js";
6
6
  import { Select as v, SelectTrigger as g, SelectValue as _, SelectContent as x, SelectItem as y } from "../../../ui/select.js";
7
- import { cn as U } from "../../../lib/utils.js";
8
- const j = {
7
+ import { cn as L } from "../../../lib/utils.js";
8
+ const B = {
9
9
  contains: "contains",
10
10
  equals: "equals",
11
11
  not_equals: "not equals",
@@ -13,7 +13,7 @@ const j = {
13
13
  ends_with: "ends with",
14
14
  is_empty: "is empty",
15
15
  is_not_empty: "is not empty"
16
- }, L = ["is_empty", "is_not_empty"], C = [
16
+ }, D = ["is_empty", "is_not_empty"], C = [
17
17
  "contains",
18
18
  "equals",
19
19
  "not_equals",
@@ -22,51 +22,53 @@ const j = {
22
22
  "is_empty",
23
23
  "is_not_empty"
24
24
  ];
25
- function B(n, u) {
25
+ function $(n, u) {
26
26
  const r = u?.[0] ?? "contains";
27
27
  return { id: crypto.randomUUID(), columnId: n, operator: r, value: "" };
28
28
  }
29
- function Q({
29
+ function Y({
30
30
  columns: n,
31
31
  columnLabel: u,
32
32
  filters: r,
33
33
  onFiltersChange: s,
34
34
  triggerLabel: d = "Filter",
35
- className: I
35
+ valuePlaceholder: I = "Value…",
36
+ clearAllLabel: N = "Clear all",
37
+ className: b
36
38
  }) {
37
- const N = (e) => u?.(e) ?? e, h = n[0], b = h?.columnId ?? "", w = () => s([...r, B(b, h?.operators)]), z = (e) => s(r.filter((c) => c.id !== e)), p = (e, c) => s(r.map((o) => o.id === e ? { ...o, ...c } : o)), F = () => s([]), i = r.length;
38
- return /* @__PURE__ */ l(T, { children: [
39
- /* @__PURE__ */ t(V, { asChild: !0, children: /* @__PURE__ */ l(
39
+ const w = (e) => u?.(e) ?? e, h = n[0], z = h?.columnId ?? "", F = () => s([...r, $(z, h?.operators)]), A = (e) => s(r.filter((c) => c.id !== e)), p = (e, c) => s(r.map((o) => o.id === e ? { ...o, ...c } : o)), E = () => s([]), i = r.length;
40
+ return /* @__PURE__ */ l(k, { children: [
41
+ /* @__PURE__ */ t(U, { asChild: !0, children: /* @__PURE__ */ l(
40
42
  m,
41
43
  {
42
44
  type: "button",
43
45
  variant: "outline",
44
46
  size: "sm",
45
47
  "data-slot": "manifest-filter",
46
- className: U(I),
48
+ className: L(b),
47
49
  "aria-label": i > 0 ? `${d} (${i} active)` : d,
48
50
  children: [
49
- /* @__PURE__ */ t(P, { className: "size-3.5" }),
51
+ /* @__PURE__ */ t(S, { className: "size-3.5" }),
50
52
  d,
51
53
  i > 0 ? /* @__PURE__ */ t("span", { className: "flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground", children: i }) : null
52
54
  ]
53
55
  }
54
56
  ) }),
55
- /* @__PURE__ */ t(k, { align: "end", className: "min-w-80", "aria-label": "Filter conditions", children: /* @__PURE__ */ l("div", { className: "flex flex-col gap-2", children: [
57
+ /* @__PURE__ */ t(j, { align: "end", className: "min-w-80", "aria-label": "Filter conditions", children: /* @__PURE__ */ l("div", { className: "flex flex-col gap-2", children: [
56
58
  r.map((e) => {
57
- const o = n.find((a) => a.columnId === e.columnId)?.operators ?? C, A = L.includes(e.operator);
59
+ const o = n.find((a) => a.columnId === e.columnId)?.operators ?? C, O = D.includes(e.operator);
58
60
  return /* @__PURE__ */ l("div", { className: "flex items-center gap-2", children: [
59
61
  /* @__PURE__ */ l(
60
62
  v,
61
63
  {
62
64
  value: e.columnId,
63
65
  onValueChange: (a) => {
64
- const f = n.find((O) => O.columnId === a)?.operators ?? C, E = f.includes(e.operator) ? e.operator : f[0] ?? "contains";
65
- p(e.id, { columnId: a, operator: E, value: "" });
66
+ const f = n.find((R) => R.columnId === a)?.operators ?? C, P = f.includes(e.operator) ? e.operator : f[0] ?? "contains";
67
+ p(e.id, { columnId: a, operator: P, value: "" });
66
68
  },
67
69
  children: [
68
70
  /* @__PURE__ */ t(g, { "aria-label": "Filter column", size: "sm", className: "w-36", children: /* @__PURE__ */ t(_, {}) }),
69
- /* @__PURE__ */ t(x, { children: n.map((a) => /* @__PURE__ */ t(y, { value: a.columnId, children: a.label ?? N(a.columnId) }, a.columnId)) })
71
+ /* @__PURE__ */ t(x, { children: n.map((a) => /* @__PURE__ */ t(y, { value: a.columnId, children: a.label ?? w(a.columnId) }, a.columnId)) })
70
72
  ]
71
73
  }
72
74
  ),
@@ -77,15 +79,15 @@ function Q({
77
79
  onValueChange: (a) => p(e.id, { operator: a, value: "" }),
78
80
  children: [
79
81
  /* @__PURE__ */ t(g, { "aria-label": "Filter operator", size: "sm", className: "w-32", children: /* @__PURE__ */ t(_, {}) }),
80
- /* @__PURE__ */ t(x, { children: o.map((a) => /* @__PURE__ */ t(y, { value: a, children: j[a] }, a)) })
82
+ /* @__PURE__ */ t(x, { children: o.map((a) => /* @__PURE__ */ t(y, { value: a, children: B[a] }, a)) })
81
83
  ]
82
84
  }
83
85
  ),
84
- A ? /* @__PURE__ */ t("div", { className: "h-8 w-40", "aria-hidden": !0 }) : /* @__PURE__ */ t(
85
- q,
86
+ O ? /* @__PURE__ */ t("div", { className: "h-8 w-40", "aria-hidden": !0 }) : /* @__PURE__ */ t(
87
+ V,
86
88
  {
87
89
  className: "w-40",
88
- placeholder: "Value…",
90
+ placeholder: I,
89
91
  value: e.value,
90
92
  onChange: (a) => p(e.id, { value: a.target.value })
91
93
  }
@@ -97,9 +99,9 @@ function Q({
97
99
  variant: "ghost",
98
100
  size: "icon",
99
101
  className: "size-8 shrink-0 text-muted-foreground hover:text-foreground",
100
- onClick: () => z(e.id),
102
+ onClick: () => A(e.id),
101
103
  "aria-label": "Remove filter",
102
- children: /* @__PURE__ */ t(R, { className: "size-3.5" })
104
+ children: /* @__PURE__ */ t(q, { className: "size-3.5" })
103
105
  }
104
106
  )
105
107
  ] }, e.id);
@@ -111,10 +113,10 @@ function Q({
111
113
  type: "button",
112
114
  variant: "outline",
113
115
  size: "sm",
114
- onClick: w,
116
+ onClick: F,
115
117
  disabled: n.length === 0,
116
118
  children: [
117
- /* @__PURE__ */ t(S, { className: "size-3.5" }),
119
+ /* @__PURE__ */ t(T, { className: "size-3.5" }),
118
120
  "Add filter"
119
121
  ]
120
122
  }
@@ -126,8 +128,8 @@ function Q({
126
128
  variant: "ghost",
127
129
  size: "sm",
128
130
  className: "text-muted-foreground",
129
- onClick: F,
130
- children: "Clear all"
131
+ onClick: E,
132
+ children: N
131
133
  }
132
134
  ) : null
133
135
  ] })
@@ -135,6 +137,6 @@ function Q({
135
137
  ] });
136
138
  }
137
139
  export {
138
- Q as ManifestFilterPopover
140
+ Y as ManifestFilterPopover
139
141
  };
140
142
  //# sourceMappingURL=ManifestFilterPopover.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ManifestFilterPopover.js","sources":["../../../../src/components/composed/PlateMapEditor/ManifestFilterPopover.tsx"],"sourcesContent":["import { ListFilterIcon, PlusIcon, XIcon } from \"lucide-react\";\n\nimport type { FilterColumnConfig, FilterCondition, FilterOperator } from \"@/components/ui/data-table/data-table\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\nimport { cn } from \"@/lib/utils\";\n\nconst OPERATOR_LABELS: Record<FilterOperator, string> = {\n contains: \"contains\",\n equals: \"equals\",\n not_equals: \"not equals\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n is_empty: \"is empty\",\n is_not_empty: \"is not empty\",\n};\n\nconst VALUE_FREE_OPERATORS: FilterOperator[] = [\"is_empty\", \"is_not_empty\"];\n\nconst DEFAULT_OPERATORS: FilterOperator[] = [\n \"contains\",\n \"equals\",\n \"not_equals\",\n \"starts_with\",\n \"ends_with\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nfunction makeCondition(columnId: string, allowedOperators?: FilterOperator[]): FilterCondition {\n const operator = allowedOperators?.[0] ?? \"contains\";\n return { id: crypto.randomUUID(), columnId, operator, value: \"\" };\n}\n\nexport interface ManifestFilterPopoverProps {\n /** Filterable columns. Operator subsets can be specified per column. */\n columns: FilterColumnConfig[];\n /** Column id → display label resolver. */\n columnLabel?: (columnId: string) => string;\n filters: FilterCondition[];\n onFiltersChange: (next: FilterCondition[]) => void;\n triggerLabel?: string;\n className?: string;\n}\n\nexport function ManifestFilterPopover({\n columns,\n columnLabel,\n filters,\n onFiltersChange,\n triggerLabel = \"Filter\",\n className,\n}: ManifestFilterPopoverProps) {\n const labelFor = (columnId: string): string => columnLabel?.(columnId) ?? columnId;\n const firstColumn = columns[0];\n const firstColumnId = firstColumn?.columnId ?? \"\";\n\n const addFilter = () => onFiltersChange([...filters, makeCondition(firstColumnId, firstColumn?.operators)]);\n const removeFilter = (id: string) => onFiltersChange(filters.filter((cond) => cond.id !== id));\n const updateFilter = (id: string, patch: Partial<FilterCondition>) =>\n onFiltersChange(filters.map((cond) => (cond.id === id ? { ...cond, ...patch } : cond)));\n const clearAll = () => onFiltersChange([]);\n\n const activeCount = filters.length;\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n data-slot=\"manifest-filter\"\n className={cn(className)}\n aria-label={activeCount > 0 ? `${triggerLabel} (${activeCount} active)` : triggerLabel}\n >\n <ListFilterIcon className=\"size-3.5\" />\n {triggerLabel}\n {activeCount > 0 ? (\n <span className=\"flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground\">\n {activeCount}\n </span>\n ) : null}\n </Button>\n </PopoverTrigger>\n\n <PopoverContent align=\"end\" className=\"min-w-80\" aria-label=\"Filter conditions\">\n <div className=\"flex flex-col gap-2\">\n {filters.map((condition) => {\n const colConfig = columns.find((c) => c.columnId === condition.columnId);\n const operators = colConfig?.operators ?? DEFAULT_OPERATORS;\n const isValueFree = VALUE_FREE_OPERATORS.includes(condition.operator);\n return (\n <div key={condition.id} className=\"flex items-center gap-2\">\n <Select\n value={condition.columnId}\n onValueChange={(value) => {\n const nextConfig = columns.find((c) => c.columnId === value);\n const nextOperators = nextConfig?.operators ?? DEFAULT_OPERATORS;\n const nextOperator = nextOperators.includes(condition.operator)\n ? condition.operator\n : (nextOperators[0] ?? \"contains\");\n updateFilter(condition.id, { columnId: value, operator: nextOperator, value: \"\" });\n }}\n >\n <SelectTrigger aria-label=\"Filter column\" size=\"sm\" className=\"w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {columns.map((c) => (\n <SelectItem key={c.columnId} value={c.columnId}>\n {c.label ?? labelFor(c.columnId)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Select\n value={condition.operator}\n onValueChange={(value) =>\n updateFilter(condition.id, { operator: value as FilterOperator, value: \"\" })\n }\n >\n <SelectTrigger aria-label=\"Filter operator\" size=\"sm\" className=\"w-32\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {operators.map((op) => (\n <SelectItem key={op} value={op}>\n {OPERATOR_LABELS[op]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {isValueFree ? (\n <div className=\"h-8 w-40\" aria-hidden />\n ) : (\n <Input\n className=\"w-40\"\n placeholder=\"Value…\"\n value={condition.value}\n onChange={(event) => updateFilter(condition.id, { value: event.target.value })}\n />\n )}\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8 shrink-0 text-muted-foreground hover:text-foreground\"\n onClick={() => removeFilter(condition.id)}\n aria-label=\"Remove filter\"\n >\n <XIcon className=\"size-3.5\" />\n </Button>\n </div>\n );\n })}\n\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={addFilter}\n disabled={columns.length === 0}\n >\n <PlusIcon className=\"size-3.5\" />\n Add filter\n </Button>\n {filters.length > 0 ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground\"\n onClick={clearAll}\n >\n Clear all\n </Button>\n ) : null}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"],"names":["OPERATOR_LABELS","VALUE_FREE_OPERATORS","DEFAULT_OPERATORS","makeCondition","columnId","allowedOperators","operator","ManifestFilterPopover","columns","columnLabel","filters","onFiltersChange","triggerLabel","className","labelFor","firstColumn","firstColumnId","addFilter","removeFilter","id","cond","updateFilter","patch","clearAll","activeCount","Popover","jsx","PopoverTrigger","jsxs","Button","cn","ListFilterIcon","PopoverContent","condition","operators","c","isValueFree","Select","value","nextOperators","nextOperator","SelectTrigger","SelectValue","SelectContent","SelectItem","op","Input","event","XIcon","PlusIcon"],"mappings":"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"}
1
+ {"version":3,"file":"ManifestFilterPopover.js","sources":["../../../../src/components/composed/PlateMapEditor/ManifestFilterPopover.tsx"],"sourcesContent":["import { ListFilterIcon, PlusIcon, XIcon } from \"lucide-react\";\n\nimport type { FilterColumnConfig, FilterCondition, FilterOperator } from \"@/components/ui/data-table/data-table\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\nimport { cn } from \"@/lib/utils\";\n\nconst OPERATOR_LABELS: Record<FilterOperator, string> = {\n contains: \"contains\",\n equals: \"equals\",\n not_equals: \"not equals\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n is_empty: \"is empty\",\n is_not_empty: \"is not empty\",\n};\n\nconst VALUE_FREE_OPERATORS: FilterOperator[] = [\"is_empty\", \"is_not_empty\"];\n\nconst DEFAULT_OPERATORS: FilterOperator[] = [\n \"contains\",\n \"equals\",\n \"not_equals\",\n \"starts_with\",\n \"ends_with\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nfunction makeCondition(columnId: string, allowedOperators?: FilterOperator[]): FilterCondition {\n const operator = allowedOperators?.[0] ?? \"contains\";\n return { id: crypto.randomUUID(), columnId, operator, value: \"\" };\n}\n\nexport interface ManifestFilterPopoverProps {\n /** Filterable columns. Operator subsets can be specified per column. */\n columns: FilterColumnConfig[];\n /** Column id → display label resolver. */\n columnLabel?: (columnId: string) => string;\n filters: FilterCondition[];\n onFiltersChange: (next: FilterCondition[]) => void;\n triggerLabel?: string;\n /** Placeholder for a condition's value input. Defaults to `\"Value…\"`. */\n valuePlaceholder?: string;\n /** Label for the clear-every-filter button. Defaults to `\"Clear all\"`. */\n clearAllLabel?: string;\n className?: string;\n}\n\nexport function ManifestFilterPopover({\n columns,\n columnLabel,\n filters,\n onFiltersChange,\n triggerLabel = \"Filter\",\n valuePlaceholder = \"Value…\",\n clearAllLabel = \"Clear all\",\n className,\n}: ManifestFilterPopoverProps) {\n const labelFor = (columnId: string): string => columnLabel?.(columnId) ?? columnId;\n const firstColumn = columns[0];\n const firstColumnId = firstColumn?.columnId ?? \"\";\n\n const addFilter = () => onFiltersChange([...filters, makeCondition(firstColumnId, firstColumn?.operators)]);\n const removeFilter = (id: string) => onFiltersChange(filters.filter((cond) => cond.id !== id));\n const updateFilter = (id: string, patch: Partial<FilterCondition>) =>\n onFiltersChange(filters.map((cond) => (cond.id === id ? { ...cond, ...patch } : cond)));\n const clearAll = () => onFiltersChange([]);\n\n const activeCount = filters.length;\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n data-slot=\"manifest-filter\"\n className={cn(className)}\n aria-label={activeCount > 0 ? `${triggerLabel} (${activeCount} active)` : triggerLabel}\n >\n <ListFilterIcon className=\"size-3.5\" />\n {triggerLabel}\n {activeCount > 0 ? (\n <span className=\"flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground\">\n {activeCount}\n </span>\n ) : null}\n </Button>\n </PopoverTrigger>\n\n <PopoverContent align=\"end\" className=\"min-w-80\" aria-label=\"Filter conditions\">\n <div className=\"flex flex-col gap-2\">\n {filters.map((condition) => {\n const colConfig = columns.find((c) => c.columnId === condition.columnId);\n const operators = colConfig?.operators ?? DEFAULT_OPERATORS;\n const isValueFree = VALUE_FREE_OPERATORS.includes(condition.operator);\n return (\n <div key={condition.id} className=\"flex items-center gap-2\">\n <Select\n value={condition.columnId}\n onValueChange={(value) => {\n const nextConfig = columns.find((c) => c.columnId === value);\n const nextOperators = nextConfig?.operators ?? DEFAULT_OPERATORS;\n const nextOperator = nextOperators.includes(condition.operator)\n ? condition.operator\n : (nextOperators[0] ?? \"contains\");\n updateFilter(condition.id, { columnId: value, operator: nextOperator, value: \"\" });\n }}\n >\n <SelectTrigger aria-label=\"Filter column\" size=\"sm\" className=\"w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {columns.map((c) => (\n <SelectItem key={c.columnId} value={c.columnId}>\n {c.label ?? labelFor(c.columnId)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Select\n value={condition.operator}\n onValueChange={(value) =>\n updateFilter(condition.id, { operator: value as FilterOperator, value: \"\" })\n }\n >\n <SelectTrigger aria-label=\"Filter operator\" size=\"sm\" className=\"w-32\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {operators.map((op) => (\n <SelectItem key={op} value={op}>\n {OPERATOR_LABELS[op]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {isValueFree ? (\n <div className=\"h-8 w-40\" aria-hidden />\n ) : (\n <Input\n className=\"w-40\"\n placeholder={valuePlaceholder}\n value={condition.value}\n onChange={(event) => updateFilter(condition.id, { value: event.target.value })}\n />\n )}\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8 shrink-0 text-muted-foreground hover:text-foreground\"\n onClick={() => removeFilter(condition.id)}\n aria-label=\"Remove filter\"\n >\n <XIcon className=\"size-3.5\" />\n </Button>\n </div>\n );\n })}\n\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={addFilter}\n disabled={columns.length === 0}\n >\n <PlusIcon className=\"size-3.5\" />\n Add filter\n </Button>\n {filters.length > 0 ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground\"\n onClick={clearAll}\n >\n {clearAllLabel}\n </Button>\n ) : null}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"],"names":["OPERATOR_LABELS","VALUE_FREE_OPERATORS","DEFAULT_OPERATORS","makeCondition","columnId","allowedOperators","operator","ManifestFilterPopover","columns","columnLabel","filters","onFiltersChange","triggerLabel","valuePlaceholder","clearAllLabel","className","labelFor","firstColumn","firstColumnId","addFilter","removeFilter","id","cond","updateFilter","patch","clearAll","activeCount","Popover","jsx","PopoverTrigger","jsxs","Button","cn","ListFilterIcon","PopoverContent","condition","operators","c","isValueFree","Select","value","nextOperators","nextOperator","SelectTrigger","SelectValue","SelectContent","SelectItem","op","Input","event","XIcon","PlusIcon"],"mappings":"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"}