@proteos/ui 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/LICENSE +105 -0
  2. package/dist/chunk-IKAX76MB.js +113 -0
  3. package/dist/chunk-IKAX76MB.js.map +1 -0
  4. package/dist/chunk-MWAXK66H.cjs +119 -0
  5. package/dist/chunk-MWAXK66H.cjs.map +1 -0
  6. package/dist/index.cjs +6246 -0
  7. package/dist/index.cjs.map +1 -0
  8. package/dist/index.d.cts +2126 -0
  9. package/dist/index.d.ts +2126 -0
  10. package/dist/index.js +6069 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/pdf-view-3ZMMS6ML.cjs +95 -0
  13. package/dist/pdf-view-3ZMMS6ML.cjs.map +1 -0
  14. package/dist/pdf-view-BV5ZD6OC.js +93 -0
  15. package/dist/pdf-view-BV5ZD6OC.js.map +1 -0
  16. package/package.json +96 -0
  17. package/src/components/attachment-chip/attachment-chip.tsx +129 -0
  18. package/src/components/attachment-chip/index.ts +2 -0
  19. package/src/components/attribute-type-icon/attribute-type-icon.stories.tsx +70 -0
  20. package/src/components/attribute-type-icon/attribute-type-icon.tsx +125 -0
  21. package/src/components/attribute-type-icon/index.ts +8 -0
  22. package/src/components/avatar/avatar.stories.tsx +42 -0
  23. package/src/components/avatar/avatar.tsx +48 -0
  24. package/src/components/avatar/index.ts +2 -0
  25. package/src/components/avatar-group/avatar-group.test.tsx +38 -0
  26. package/src/components/avatar-group/avatar-group.tsx +60 -0
  27. package/src/components/avatar-group/index.ts +2 -0
  28. package/src/components/badge/badge.stories.tsx +62 -0
  29. package/src/components/badge/badge.test.tsx +36 -0
  30. package/src/components/badge/badge.tsx +54 -0
  31. package/src/components/badge/index.ts +2 -0
  32. package/src/components/badge-multi-select/badge-multi-select.stories.tsx +177 -0
  33. package/src/components/badge-multi-select/badge-multi-select.test.tsx +155 -0
  34. package/src/components/badge-multi-select/badge-multi-select.tsx +272 -0
  35. package/src/components/badge-multi-select/index.ts +2 -0
  36. package/src/components/breadcrumbs/breadcrumbs.stories.tsx +43 -0
  37. package/src/components/breadcrumbs/breadcrumbs.tsx +86 -0
  38. package/src/components/breadcrumbs/index.ts +2 -0
  39. package/src/components/button/button.stories.tsx +290 -0
  40. package/src/components/button/button.test.tsx +59 -0
  41. package/src/components/button/button.tsx +86 -0
  42. package/src/components/button/index.ts +2 -0
  43. package/src/components/card/card.stories.tsx +351 -0
  44. package/src/components/card/card.test.tsx +141 -0
  45. package/src/components/card/card.tsx +173 -0
  46. package/src/components/card/index.ts +13 -0
  47. package/src/components/checkbox/checkbox-group.tsx +52 -0
  48. package/src/components/checkbox/checkbox.stories.tsx +48 -0
  49. package/src/components/checkbox/checkbox.test.tsx +50 -0
  50. package/src/components/checkbox/checkbox.tsx +71 -0
  51. package/src/components/checkbox/index.ts +4 -0
  52. package/src/components/combobox/combobox.stories.tsx +97 -0
  53. package/src/components/combobox/combobox.test.tsx +123 -0
  54. package/src/components/combobox/combobox.tsx +239 -0
  55. package/src/components/combobox/index.ts +2 -0
  56. package/src/components/command/command-hint.tsx +46 -0
  57. package/src/components/command/command.stories.tsx +88 -0
  58. package/src/components/command/command.test.tsx +102 -0
  59. package/src/components/command/command.tsx +76 -0
  60. package/src/components/command/index.ts +16 -0
  61. package/src/components/currency-input/currency-input.tsx +192 -0
  62. package/src/components/currency-input/index.ts +6 -0
  63. package/src/components/data-table/cells.stories.tsx +120 -0
  64. package/src/components/data-table/cells.tsx +165 -0
  65. package/src/components/data-table/data-table.stories.tsx +371 -0
  66. package/src/components/data-table/data-table.tsx +556 -0
  67. package/src/components/data-table/index.ts +22 -0
  68. package/src/components/data-table/make-actions-column.ts +30 -0
  69. package/src/components/data-table/states/data-table-empty.tsx +40 -0
  70. package/src/components/data-table/states/data-table-error.tsx +30 -0
  71. package/src/components/data-table/states/data-table-skeleton.tsx +42 -0
  72. package/src/components/data-table/use-infinite-scroll-sentinel.ts +51 -0
  73. package/src/components/date-picker/calendar-internals.tsx +138 -0
  74. package/src/components/date-picker/date-picker.stories.tsx +78 -0
  75. package/src/components/date-picker/date-picker.test.tsx +71 -0
  76. package/src/components/date-picker/date-picker.tsx +140 -0
  77. package/src/components/date-picker/index.ts +2 -0
  78. package/src/components/date-time-picker/date-time-picker.stories.tsx +96 -0
  79. package/src/components/date-time-picker/date-time-picker.test.tsx +87 -0
  80. package/src/components/date-time-picker/date-time-picker.tsx +203 -0
  81. package/src/components/date-time-picker/index.ts +2 -0
  82. package/src/components/empty-state/empty-state.tsx +63 -0
  83. package/src/components/empty-state/index.ts +2 -0
  84. package/src/components/error-animation/error-animation.stories.tsx +50 -0
  85. package/src/components/error-animation/error-animation.test.tsx +22 -0
  86. package/src/components/error-animation/error-animation.tsx +26 -0
  87. package/src/components/error-animation/index.ts +2 -0
  88. package/src/components/field/field.tsx +142 -0
  89. package/src/components/field/index.ts +8 -0
  90. package/src/components/file-field/file-field.tsx +285 -0
  91. package/src/components/file-field/index.ts +2 -0
  92. package/src/components/file-viewer/fallback-card.tsx +68 -0
  93. package/src/components/file-viewer/file-viewer.stories.tsx +67 -0
  94. package/src/components/file-viewer/file-viewer.test.tsx +81 -0
  95. package/src/components/file-viewer/file-viewer.tsx +116 -0
  96. package/src/components/file-viewer/image-view.tsx +38 -0
  97. package/src/components/file-viewer/index.ts +7 -0
  98. package/src/components/file-viewer/pdf-view.tsx +122 -0
  99. package/src/components/file-viewer/video-view.tsx +16 -0
  100. package/src/components/image-attachment/image-attachment.stories.tsx +39 -0
  101. package/src/components/image-attachment/image-attachment.test.tsx +54 -0
  102. package/src/components/image-attachment/image-attachment.tsx +77 -0
  103. package/src/components/image-attachment/index.ts +3 -0
  104. package/src/components/image-attachment/is-previewable-image-name.ts +14 -0
  105. package/src/components/image-lightbox/image-lightbox.stories.tsx +38 -0
  106. package/src/components/image-lightbox/image-lightbox.test.tsx +72 -0
  107. package/src/components/image-lightbox/image-lightbox.tsx +92 -0
  108. package/src/components/image-lightbox/index.ts +2 -0
  109. package/src/components/input/index.ts +2 -0
  110. package/src/components/input/input.stories.tsx +71 -0
  111. package/src/components/input/input.test.tsx +36 -0
  112. package/src/components/input/input.tsx +76 -0
  113. package/src/components/kbd/index.ts +2 -0
  114. package/src/components/kbd/kbd.stories.tsx +34 -0
  115. package/src/components/kbd/kbd.tsx +27 -0
  116. package/src/components/menu/index.ts +2 -0
  117. package/src/components/menu/menu.tsx +121 -0
  118. package/src/components/modal/index.ts +10 -0
  119. package/src/components/modal/modal.stories.tsx +153 -0
  120. package/src/components/modal/modal.test.tsx +93 -0
  121. package/src/components/modal/modal.tsx +149 -0
  122. package/src/components/multi-select/index.ts +2 -0
  123. package/src/components/multi-select/multi-select.stories.tsx +211 -0
  124. package/src/components/multi-select/multi-select.test.tsx +151 -0
  125. package/src/components/multi-select/multi-select.tsx +339 -0
  126. package/src/components/nav/index.ts +7 -0
  127. package/src/components/nav/nav.stories.tsx +139 -0
  128. package/src/components/nav/nav.tsx +246 -0
  129. package/src/components/popover/index.ts +8 -0
  130. package/src/components/popover/popover.stories.tsx +92 -0
  131. package/src/components/popover/popover.tsx +135 -0
  132. package/src/components/progress-bar/index.ts +2 -0
  133. package/src/components/progress-bar/progress-bar.stories.tsx +75 -0
  134. package/src/components/progress-bar/progress-bar.test.tsx +29 -0
  135. package/src/components/progress-bar/progress-bar.tsx +57 -0
  136. package/src/components/radio-group/index.ts +2 -0
  137. package/src/components/radio-group/radio-group.stories.tsx +113 -0
  138. package/src/components/radio-group/radio-group.test.tsx +87 -0
  139. package/src/components/radio-group/radio-group.tsx +104 -0
  140. package/src/components/record-filter/attribute-picker.tsx +74 -0
  141. package/src/components/record-filter/chip-value.tsx +171 -0
  142. package/src/components/record-filter/filter-row.tsx +262 -0
  143. package/src/components/record-filter/filter-value-input.tsx +351 -0
  144. package/src/components/record-filter/group-add-controls.tsx +77 -0
  145. package/src/components/record-filter/group-body.tsx +173 -0
  146. package/src/components/record-filter/group-mutations.test.ts +104 -0
  147. package/src/components/record-filter/group-mutations.ts +116 -0
  148. package/src/components/record-filter/index.ts +58 -0
  149. package/src/components/record-filter/nested-group.tsx +138 -0
  150. package/src/components/record-filter/operator-picker.tsx +62 -0
  151. package/src/components/record-filter/operators.test.ts +105 -0
  152. package/src/components/record-filter/operators.ts +97 -0
  153. package/src/components/record-filter/record-filter-builder-panel.tsx +236 -0
  154. package/src/components/record-filter/record-filter-button.tsx +126 -0
  155. package/src/components/record-filter/record-filter-chips.tsx +527 -0
  156. package/src/components/record-filter/record-filter-editor.tsx +91 -0
  157. package/src/components/record-filter/record-filter.stories.tsx +196 -0
  158. package/src/components/record-filter/record-filter.test.tsx +437 -0
  159. package/src/components/record-filter/show-details-store.ts +72 -0
  160. package/src/components/record-filter/types.ts +150 -0
  161. package/src/components/segmented-control/index.ts +6 -0
  162. package/src/components/segmented-control/segmented-control.stories.tsx +67 -0
  163. package/src/components/segmented-control/segmented-control.test.tsx +47 -0
  164. package/src/components/segmented-control/segmented-control.tsx +105 -0
  165. package/src/components/select/index.ts +2 -0
  166. package/src/components/select/select.stories.tsx +76 -0
  167. package/src/components/select/select.test.tsx +56 -0
  168. package/src/components/select/select.tsx +159 -0
  169. package/src/components/separator/index.ts +2 -0
  170. package/src/components/separator/separator.stories.tsx +73 -0
  171. package/src/components/separator/separator.test.tsx +29 -0
  172. package/src/components/separator/separator.tsx +51 -0
  173. package/src/components/skeleton/index.ts +2 -0
  174. package/src/components/skeleton/skeleton.stories.tsx +68 -0
  175. package/src/components/skeleton/skeleton.test.tsx +38 -0
  176. package/src/components/skeleton/skeleton.tsx +43 -0
  177. package/src/components/success-animation/index.ts +2 -0
  178. package/src/components/success-animation/success-animation.stories.tsx +50 -0
  179. package/src/components/success-animation/success-animation.test.tsx +22 -0
  180. package/src/components/success-animation/success-animation.tsx +26 -0
  181. package/src/components/switch/index.ts +2 -0
  182. package/src/components/switch/switch.stories.tsx +60 -0
  183. package/src/components/switch/switch.test.tsx +50 -0
  184. package/src/components/switch/switch.tsx +49 -0
  185. package/src/components/table/index.ts +25 -0
  186. package/src/components/table/table.stories.tsx +306 -0
  187. package/src/components/table/table.test.tsx +115 -0
  188. package/src/components/table/table.tsx +543 -0
  189. package/src/components/tabs/index.ts +8 -0
  190. package/src/components/tabs/tabs.tsx +141 -0
  191. package/src/components/tag-input/index.ts +2 -0
  192. package/src/components/tag-input/tag-input.stories.tsx +73 -0
  193. package/src/components/tag-input/tag-input.test.tsx +80 -0
  194. package/src/components/tag-input/tag-input.tsx +193 -0
  195. package/src/components/textarea/index.ts +2 -0
  196. package/src/components/textarea/textarea.stories.tsx +75 -0
  197. package/src/components/textarea/textarea.test.tsx +41 -0
  198. package/src/components/textarea/textarea.tsx +86 -0
  199. package/src/components/time-field/index.ts +2 -0
  200. package/src/components/time-field/time-field.stories.tsx +76 -0
  201. package/src/components/time-field/time-field.test.tsx +51 -0
  202. package/src/components/time-field/time-field.tsx +98 -0
  203. package/src/components/tooltip/index.ts +2 -0
  204. package/src/components/tooltip/tooltip.stories.tsx +176 -0
  205. package/src/components/tooltip/tooltip.test.tsx +52 -0
  206. package/src/components/tooltip/tooltip.tsx +56 -0
  207. package/src/index.ts +47 -0
  208. package/src/lib/cn.ts +6 -0
  209. package/src/lib/commands/discovery-store.test.tsx +76 -0
  210. package/src/lib/commands/discovery-store.ts +110 -0
  211. package/src/lib/commands/index.ts +9 -0
  212. package/src/lib/commands/match-event.test.ts +99 -0
  213. package/src/lib/commands/match-event.ts +31 -0
  214. package/src/lib/commands/parse-combo.test.ts +65 -0
  215. package/src/lib/commands/parse-combo.ts +48 -0
  216. package/src/lib/commands/platform.ts +27 -0
  217. package/src/lib/commands/protected-combos.test.ts +18 -0
  218. package/src/lib/commands/protected-combos.ts +38 -0
  219. package/src/lib/commands/registry.test.ts +97 -0
  220. package/src/lib/commands/registry.ts +59 -0
  221. package/src/lib/commands/use-command.test.tsx +91 -0
  222. package/src/lib/commands/use-command.ts +32 -0
  223. package/src/lib/commands/use-escape-key.test.tsx +97 -0
  224. package/src/lib/commands/use-escape-key.ts +62 -0
  225. package/src/styles.css +321 -0
  226. package/src/test/setup.ts +9 -0
@@ -0,0 +1,95 @@
1
+ 'use strict';
2
+
3
+ var chunkMWAXK66H_cjs = require('./chunk-MWAXK66H.cjs');
4
+ var lucideReact = require('lucide-react');
5
+ var react = require('react');
6
+ var reactPdf = require('react-pdf');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+
9
+ // url-asset:pdfjs-dist/build/pdf.worker.min.mjs?url
10
+ var pdf_worker_min_default = "https://unpkg.com/pdfjs-dist@5.4.296/build/pdf.worker.min.mjs";
11
+ if (!reactPdf.pdfjs.GlobalWorkerOptions.workerSrc) {
12
+ reactPdf.pdfjs.GlobalWorkerOptions.workerSrc = pdf_worker_min_default;
13
+ }
14
+ function PdfView({ name, src, onDownload }) {
15
+ const [pageCount, setPageCount] = react.useState(null);
16
+ const [pageNumber, setPageNumber] = react.useState(1);
17
+ const [loadError, setLoadError] = react.useState(false);
18
+ const scrollRef = react.useRef(null);
19
+ const [pageWidth, setPageWidth] = react.useState(null);
20
+ react.useEffect(() => {
21
+ const element = scrollRef.current;
22
+ if (!element) return;
23
+ const observer = new ResizeObserver(([entry]) => {
24
+ if (entry) setPageWidth(Math.floor(entry.contentRect.width));
25
+ });
26
+ observer.observe(element);
27
+ return () => observer.disconnect();
28
+ }, []);
29
+ if (loadError) {
30
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full w-full items-center justify-center p-4", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-sans text-[13px] text-danger", children: "Could not display this PDF. Download it instead." }) });
31
+ }
32
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full w-full flex-col", children: [
33
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: scrollRef, className: "min-h-0 flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
34
+ reactPdf.Document,
35
+ {
36
+ file: src,
37
+ onLoadSuccess: ({ numPages }) => {
38
+ setPageCount(numPages);
39
+ setPageNumber(1);
40
+ },
41
+ onLoadError: () => setLoadError(true),
42
+ loading: /* @__PURE__ */ jsxRuntime.jsx(chunkMWAXK66H_cjs.Skeleton, { "aria-label": `Loading ${name}`, className: "h-full w-full rounded-none" }),
43
+ error: null,
44
+ children: pageWidth ? /* @__PURE__ */ jsxRuntime.jsx(
45
+ reactPdf.Page,
46
+ {
47
+ pageNumber,
48
+ width: pageWidth,
49
+ renderTextLayer: false,
50
+ renderAnnotationLayer: false
51
+ }
52
+ ) : null
53
+ }
54
+ ) }),
55
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center justify-center gap-1.5 border-t border-rule bg-surface px-2 py-1", children: [
56
+ /* @__PURE__ */ jsxRuntime.jsx(
57
+ chunkMWAXK66H_cjs.Button,
58
+ {
59
+ variant: "ghost",
60
+ size: "icon-sm",
61
+ "aria-label": "Previous page",
62
+ isDisabled: pageNumber <= 1,
63
+ onPress: () => setPageNumber((page) => Math.max(1, page - 1)),
64
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { "aria-hidden": true })
65
+ }
66
+ ),
67
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-14 text-center font-sans text-[12px] tabular-nums text-ink-3", children: pageCount ? `${pageNumber} / ${pageCount}` : "\u2013" }),
68
+ /* @__PURE__ */ jsxRuntime.jsx(
69
+ chunkMWAXK66H_cjs.Button,
70
+ {
71
+ variant: "ghost",
72
+ size: "icon-sm",
73
+ "aria-label": "Next page",
74
+ isDisabled: pageCount === null || pageNumber >= pageCount,
75
+ onPress: () => setPageNumber((page) => Math.min(pageCount ?? page, page + 1)),
76
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true })
77
+ }
78
+ ),
79
+ onDownload ? /* @__PURE__ */ jsxRuntime.jsx(
80
+ chunkMWAXK66H_cjs.Button,
81
+ {
82
+ variant: "ghost",
83
+ size: "icon-sm",
84
+ "aria-label": `Download ${name}`,
85
+ onPress: onDownload,
86
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { "aria-hidden": true })
87
+ }
88
+ ) : null
89
+ ] })
90
+ ] });
91
+ }
92
+
93
+ module.exports = PdfView;
94
+ //# sourceMappingURL=pdf-view-3ZMMS6ML.cjs.map
95
+ //# sourceMappingURL=pdf-view-3ZMMS6ML.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["url-asset:pdfjs-dist/build/pdf.worker.min.mjs?url","../src/components/file-viewer/pdf-view.tsx"],"names":["pdfjs","useState","useRef","useEffect","jsx","jsxs","Document","Skeleton","Page","Button","ChevronLeft","ChevronRight","Download"],"mappings":"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","file":"pdf-view-3ZMMS6ML.cjs","sourcesContent":["export default \"https://unpkg.com/pdfjs-dist@5.4.296/build/pdf.worker.min.mjs\"","import { ChevronLeft, ChevronRight, Download } from 'lucide-react'\nimport pdfWorkerUrl from 'pdfjs-dist/build/pdf.worker.min.mjs?url'\nimport { useEffect, useRef, useState } from 'react'\nimport { Document, Page, pdfjs } from 'react-pdf'\n\nimport { Button } from '../button/button'\nimport { Skeleton } from '../skeleton/skeleton'\n\n/* =========================================================================\n PdfView — the FileViewer's PDF pane, backed by react-pdf (pdf.js).\n Lazy-loaded by the FileViewer (default export) so pdf.js and its worker\n stay out of the main bundle. Text/annotation layers are off: this is a\n read-only preview and the layers would need pdf.js's own stylesheets,\n which the token-based design system deliberately doesn't import.\n ========================================================================= */\n\n// The worker must come from the SAME pdfjs-dist instance react-pdf renders\n// with (API/worker version mismatch throws). `?url` lets Vite emit it as an\n// asset and hand back the served URL. In the published dist build the `?url`\n// module is rewritten to a version-pinned CDN URL (see tsup.config.ts), and\n// the guard lets consumers pre-set their own workerSrc before this lazy\n// chunk loads.\nif (!pdfjs.GlobalWorkerOptions.workerSrc) {\n pdfjs.GlobalWorkerOptions.workerSrc = pdfWorkerUrl\n}\n\nexport interface PdfViewProps {\n name: string\n /** Blob object URL of the PDF bytes. */\n src: string\n onDownload?: () => void\n}\n\nexport default function PdfView({ name, src, onDownload }: PdfViewProps) {\n const [pageCount, setPageCount] = useState<number | null>(null)\n const [pageNumber, setPageNumber] = useState(1)\n const [loadError, setLoadError] = useState(false)\n\n // Fit-width: render the page at the scroll area's current width.\n const scrollRef = useRef<HTMLDivElement | null>(null)\n const [pageWidth, setPageWidth] = useState<number | null>(null)\n useEffect(() => {\n const element = scrollRef.current\n if (!element) return\n const observer = new ResizeObserver(([entry]) => {\n if (entry) setPageWidth(Math.floor(entry.contentRect.width))\n })\n observer.observe(element)\n return () => observer.disconnect()\n }, [])\n\n if (loadError) {\n return (\n <div className=\"flex h-full w-full items-center justify-center p-4\">\n <span className=\"font-sans text-[13px] text-danger\">\n Could not display this PDF. Download it instead.\n </span>\n </div>\n )\n }\n\n return (\n <div className=\"flex h-full w-full flex-col\">\n <div ref={scrollRef} className=\"min-h-0 flex-1 overflow-auto\">\n <Document\n file={src}\n onLoadSuccess={({ numPages }) => {\n setPageCount(numPages)\n setPageNumber(1)\n }}\n onLoadError={() => setLoadError(true)}\n loading={\n <Skeleton aria-label={`Loading ${name}`} className=\"h-full w-full rounded-none\" />\n }\n error={null}\n >\n {pageWidth ? (\n <Page\n pageNumber={pageNumber}\n width={pageWidth}\n renderTextLayer={false}\n renderAnnotationLayer={false}\n />\n ) : null}\n </Document>\n </div>\n <div className=\"flex shrink-0 items-center justify-center gap-1.5 border-t border-rule bg-surface px-2 py-1\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Previous page\"\n isDisabled={pageNumber <= 1}\n onPress={() => setPageNumber((page) => Math.max(1, page - 1))}\n >\n <ChevronLeft aria-hidden />\n </Button>\n <span className=\"min-w-14 text-center font-sans text-[12px] tabular-nums text-ink-3\">\n {pageCount ? `${pageNumber} / ${pageCount}` : '–'}\n </span>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Next page\"\n isDisabled={pageCount === null || pageNumber >= pageCount}\n onPress={() => setPageNumber((page) => Math.min(pageCount ?? page, page + 1))}\n >\n <ChevronRight aria-hidden />\n </Button>\n {onDownload ? (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={`Download ${name}`}\n onPress={onDownload}\n >\n <Download aria-hidden />\n </Button>\n ) : null}\n </div>\n </div>\n )\n}\n"]}
@@ -0,0 +1,93 @@
1
+ import { Skeleton, Button } from './chunk-IKAX76MB.js';
2
+ import { ChevronLeft, ChevronRight, Download } from 'lucide-react';
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { pdfjs, Document, Page } from 'react-pdf';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ // url-asset:pdfjs-dist/build/pdf.worker.min.mjs?url
8
+ var pdf_worker_min_default = "https://unpkg.com/pdfjs-dist@5.4.296/build/pdf.worker.min.mjs";
9
+ if (!pdfjs.GlobalWorkerOptions.workerSrc) {
10
+ pdfjs.GlobalWorkerOptions.workerSrc = pdf_worker_min_default;
11
+ }
12
+ function PdfView({ name, src, onDownload }) {
13
+ const [pageCount, setPageCount] = useState(null);
14
+ const [pageNumber, setPageNumber] = useState(1);
15
+ const [loadError, setLoadError] = useState(false);
16
+ const scrollRef = useRef(null);
17
+ const [pageWidth, setPageWidth] = useState(null);
18
+ useEffect(() => {
19
+ const element = scrollRef.current;
20
+ if (!element) return;
21
+ const observer = new ResizeObserver(([entry]) => {
22
+ if (entry) setPageWidth(Math.floor(entry.contentRect.width));
23
+ });
24
+ observer.observe(element);
25
+ return () => observer.disconnect();
26
+ }, []);
27
+ if (loadError) {
28
+ return /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center p-4", children: /* @__PURE__ */ jsx("span", { className: "font-sans text-[13px] text-danger", children: "Could not display this PDF. Download it instead." }) });
29
+ }
30
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full flex-col", children: [
31
+ /* @__PURE__ */ jsx("div", { ref: scrollRef, className: "min-h-0 flex-1 overflow-auto", children: /* @__PURE__ */ jsx(
32
+ Document,
33
+ {
34
+ file: src,
35
+ onLoadSuccess: ({ numPages }) => {
36
+ setPageCount(numPages);
37
+ setPageNumber(1);
38
+ },
39
+ onLoadError: () => setLoadError(true),
40
+ loading: /* @__PURE__ */ jsx(Skeleton, { "aria-label": `Loading ${name}`, className: "h-full w-full rounded-none" }),
41
+ error: null,
42
+ children: pageWidth ? /* @__PURE__ */ jsx(
43
+ Page,
44
+ {
45
+ pageNumber,
46
+ width: pageWidth,
47
+ renderTextLayer: false,
48
+ renderAnnotationLayer: false
49
+ }
50
+ ) : null
51
+ }
52
+ ) }),
53
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-center gap-1.5 border-t border-rule bg-surface px-2 py-1", children: [
54
+ /* @__PURE__ */ jsx(
55
+ Button,
56
+ {
57
+ variant: "ghost",
58
+ size: "icon-sm",
59
+ "aria-label": "Previous page",
60
+ isDisabled: pageNumber <= 1,
61
+ onPress: () => setPageNumber((page) => Math.max(1, page - 1)),
62
+ children: /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": true })
63
+ }
64
+ ),
65
+ /* @__PURE__ */ jsx("span", { className: "min-w-14 text-center font-sans text-[12px] tabular-nums text-ink-3", children: pageCount ? `${pageNumber} / ${pageCount}` : "\u2013" }),
66
+ /* @__PURE__ */ jsx(
67
+ Button,
68
+ {
69
+ variant: "ghost",
70
+ size: "icon-sm",
71
+ "aria-label": "Next page",
72
+ isDisabled: pageCount === null || pageNumber >= pageCount,
73
+ onPress: () => setPageNumber((page) => Math.min(pageCount ?? page, page + 1)),
74
+ children: /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true })
75
+ }
76
+ ),
77
+ onDownload ? /* @__PURE__ */ jsx(
78
+ Button,
79
+ {
80
+ variant: "ghost",
81
+ size: "icon-sm",
82
+ "aria-label": `Download ${name}`,
83
+ onPress: onDownload,
84
+ children: /* @__PURE__ */ jsx(Download, { "aria-hidden": true })
85
+ }
86
+ ) : null
87
+ ] })
88
+ ] });
89
+ }
90
+
91
+ export { PdfView as default };
92
+ //# sourceMappingURL=pdf-view-BV5ZD6OC.js.map
93
+ //# sourceMappingURL=pdf-view-BV5ZD6OC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["url-asset:pdfjs-dist/build/pdf.worker.min.mjs?url","../src/components/file-viewer/pdf-view.tsx"],"names":[],"mappings":"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","file":"pdf-view-BV5ZD6OC.js","sourcesContent":["export default \"https://unpkg.com/pdfjs-dist@5.4.296/build/pdf.worker.min.mjs\"","import { ChevronLeft, ChevronRight, Download } from 'lucide-react'\nimport pdfWorkerUrl from 'pdfjs-dist/build/pdf.worker.min.mjs?url'\nimport { useEffect, useRef, useState } from 'react'\nimport { Document, Page, pdfjs } from 'react-pdf'\n\nimport { Button } from '../button/button'\nimport { Skeleton } from '../skeleton/skeleton'\n\n/* =========================================================================\n PdfView — the FileViewer's PDF pane, backed by react-pdf (pdf.js).\n Lazy-loaded by the FileViewer (default export) so pdf.js and its worker\n stay out of the main bundle. Text/annotation layers are off: this is a\n read-only preview and the layers would need pdf.js's own stylesheets,\n which the token-based design system deliberately doesn't import.\n ========================================================================= */\n\n// The worker must come from the SAME pdfjs-dist instance react-pdf renders\n// with (API/worker version mismatch throws). `?url` lets Vite emit it as an\n// asset and hand back the served URL. In the published dist build the `?url`\n// module is rewritten to a version-pinned CDN URL (see tsup.config.ts), and\n// the guard lets consumers pre-set their own workerSrc before this lazy\n// chunk loads.\nif (!pdfjs.GlobalWorkerOptions.workerSrc) {\n pdfjs.GlobalWorkerOptions.workerSrc = pdfWorkerUrl\n}\n\nexport interface PdfViewProps {\n name: string\n /** Blob object URL of the PDF bytes. */\n src: string\n onDownload?: () => void\n}\n\nexport default function PdfView({ name, src, onDownload }: PdfViewProps) {\n const [pageCount, setPageCount] = useState<number | null>(null)\n const [pageNumber, setPageNumber] = useState(1)\n const [loadError, setLoadError] = useState(false)\n\n // Fit-width: render the page at the scroll area's current width.\n const scrollRef = useRef<HTMLDivElement | null>(null)\n const [pageWidth, setPageWidth] = useState<number | null>(null)\n useEffect(() => {\n const element = scrollRef.current\n if (!element) return\n const observer = new ResizeObserver(([entry]) => {\n if (entry) setPageWidth(Math.floor(entry.contentRect.width))\n })\n observer.observe(element)\n return () => observer.disconnect()\n }, [])\n\n if (loadError) {\n return (\n <div className=\"flex h-full w-full items-center justify-center p-4\">\n <span className=\"font-sans text-[13px] text-danger\">\n Could not display this PDF. Download it instead.\n </span>\n </div>\n )\n }\n\n return (\n <div className=\"flex h-full w-full flex-col\">\n <div ref={scrollRef} className=\"min-h-0 flex-1 overflow-auto\">\n <Document\n file={src}\n onLoadSuccess={({ numPages }) => {\n setPageCount(numPages)\n setPageNumber(1)\n }}\n onLoadError={() => setLoadError(true)}\n loading={\n <Skeleton aria-label={`Loading ${name}`} className=\"h-full w-full rounded-none\" />\n }\n error={null}\n >\n {pageWidth ? (\n <Page\n pageNumber={pageNumber}\n width={pageWidth}\n renderTextLayer={false}\n renderAnnotationLayer={false}\n />\n ) : null}\n </Document>\n </div>\n <div className=\"flex shrink-0 items-center justify-center gap-1.5 border-t border-rule bg-surface px-2 py-1\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Previous page\"\n isDisabled={pageNumber <= 1}\n onPress={() => setPageNumber((page) => Math.max(1, page - 1))}\n >\n <ChevronLeft aria-hidden />\n </Button>\n <span className=\"min-w-14 text-center font-sans text-[12px] tabular-nums text-ink-3\">\n {pageCount ? `${pageNumber} / ${pageCount}` : '–'}\n </span>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Next page\"\n isDisabled={pageCount === null || pageNumber >= pageCount}\n onPress={() => setPageNumber((page) => Math.min(pageCount ?? page, page + 1))}\n >\n <ChevronRight aria-hidden />\n </Button>\n {onDownload ? (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={`Download ${name}`}\n onPress={onDownload}\n >\n <Download aria-hidden />\n </Button>\n ) : null}\n </div>\n </div>\n )\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "@proteos/ui",
3
+ "version": "0.31.0",
4
+ "license": "FSL-1.1-Apache-2.0",
5
+ "description": "Proteos React component library (React Aria Components + Tailwind v4).",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/proteos-ai/ui.git"
9
+ },
10
+ "homepage": "https://github.com/proteos-ai/ui",
11
+ "bugs": "https://github.com/proteos-ai/ui/issues",
12
+ "type": "module",
13
+ "sideEffects": [
14
+ "**/*.css"
15
+ ],
16
+ "exports": {
17
+ ".": {
18
+ "import": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "require": {
23
+ "types": "./dist/index.d.cts",
24
+ "default": "./dist/index.cjs"
25
+ }
26
+ },
27
+ "./styles.css": "./src/styles.css"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "provenance": false
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "src"
36
+ ],
37
+ "engines": {
38
+ "node": ">=20.0.0"
39
+ },
40
+ "peerDependencies": {
41
+ "react": ">=19.0.0",
42
+ "react-dom": ">=19.0.0"
43
+ },
44
+ "dependencies": {
45
+ "@atlaskit/pragmatic-drag-and-drop": "^1.8.1",
46
+ "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.1.0",
47
+ "@internationalized/date": "^3.10.0",
48
+ "@tanstack/react-table": "^8.21.3",
49
+ "@tanstack/react-virtual": "^3.13.24",
50
+ "clsx": "^2.1.1",
51
+ "lucide-react": "^0.473.0",
52
+ "pdfjs-dist": "5.4.296",
53
+ "react-aria-components": "^1.17.0",
54
+ "react-pdf": "^10.4.1",
55
+ "tailwind-merge": "^3.5.0",
56
+ "tailwind-variants": "^3.2.2",
57
+ "tailwindcss": "^4.2.4",
58
+ "@proteos/sdk": "0.31.0"
59
+ },
60
+ "devDependencies": {
61
+ "@biomejs/biome": "^2.4.13",
62
+ "@storybook/addon-a11y": "^10.3.5",
63
+ "@storybook/addon-docs": "^10.3.5",
64
+ "@storybook/react-vite": "^10.3.5",
65
+ "@tailwindcss/vite": "^4.2.4",
66
+ "@testing-library/jest-dom": "^6.9.1",
67
+ "@testing-library/react": "^16.3.2",
68
+ "@testing-library/user-event": "^14.6.1",
69
+ "@types/react": "^19.2.14",
70
+ "@types/react-dom": "^19.2.3",
71
+ "@vitejs/plugin-react": "^6.0.1",
72
+ "jsdom": "^29.0.2",
73
+ "react": "^19.2.5",
74
+ "react-dom": "^19.2.5",
75
+ "storybook": "^10.3.5",
76
+ "tsup": "^8.3.0",
77
+ "typescript": "^6.0.3",
78
+ "vite": "^8.0.10",
79
+ "vitest": "^3.2.4",
80
+ "@proteos/biome-config": "0.0.0",
81
+ "@proteos/tsconfig": "0.0.0"
82
+ },
83
+ "scripts": {
84
+ "lint": "biome check .",
85
+ "format": "biome format --write .",
86
+ "typecheck": "tsc -b",
87
+ "test": "vitest run",
88
+ "test:watch": "vitest",
89
+ "storybook": "storybook dev -p 6006",
90
+ "build": "tsc --noEmit && storybook build -o dist-storybook",
91
+ "build:lib": "tsup"
92
+ },
93
+ "main": "./dist/index.cjs",
94
+ "module": "./dist/index.js",
95
+ "types": "./dist/index.d.ts"
96
+ }
@@ -0,0 +1,129 @@
1
+ import { Loader2 } from 'lucide-react'
2
+ import type { ReactNode } from 'react'
3
+ import { tv, type VariantProps } from 'tailwind-variants'
4
+
5
+ import { cn } from '../../lib/cn'
6
+ import { formatFileSize, iconForContentType } from '../file-field'
7
+
8
+ /* =========================================================================
9
+ AttachmentChip — a small file token for chat composers and message
10
+ bubbles. A file-type icon (or a spinner while uploading), a truncated
11
+ name, the size (or upload state), and an optional (x) to remove. Pure
12
+ presentation: the consumer owns upload / remove / download.
13
+ ========================================================================= */
14
+
15
+ export const attachmentChipStyles = tv({
16
+ base: [
17
+ 'inline-flex items-center gap-1.5 max-w-[220px]',
18
+ 'pl-2 pr-1 py-1 rounded-[6px] border',
19
+ 'font-sans text-[12.5px] leading-none',
20
+ ],
21
+ variants: {
22
+ status: {
23
+ uploading: 'bg-surface-2 border-rule text-ink-3',
24
+ ready: 'bg-surface-2 border-rule text-ink',
25
+ error: 'bg-surface-2 border-danger text-danger',
26
+ },
27
+ isInteractive: {
28
+ true: 'cursor-pointer hover:bg-surface-3',
29
+ false: '',
30
+ },
31
+ },
32
+ defaultVariants: { status: 'ready', isInteractive: false },
33
+ })
34
+
35
+ export type AttachmentChipVariants = VariantProps<typeof attachmentChipStyles>
36
+
37
+ export interface AttachmentChipProps {
38
+ /** File name shown (truncated). */
39
+ name: string
40
+ /** Size in bytes — rendered when known and the chip is in the `ready` state. */
41
+ sizeInBytes?: number
42
+ /** MIME type — picks the leading file-type icon. */
43
+ contentType?: string
44
+ /** Upload lifecycle: spinner while `uploading`, danger styling on `error`. */
45
+ status?: 'uploading' | 'ready' | 'error'
46
+ /** Tooltip text and the meta line shown in the `error` state (the failure reason). */
47
+ errorMessage?: string
48
+ /** When set, an (x) button is shown that calls this. */
49
+ onRemove?: () => void
50
+ /** When set, the chip body is pressable (e.g. to download an agent file). */
51
+ onPress?: () => void
52
+ className?: string
53
+ }
54
+
55
+ export function AttachmentChip({
56
+ name,
57
+ sizeInBytes,
58
+ contentType,
59
+ status = 'ready',
60
+ errorMessage,
61
+ onRemove,
62
+ onPress,
63
+ className,
64
+ }: AttachmentChipProps) {
65
+ const Icon = status === 'uploading' ? Loader2 : iconForContentType(contentType)
66
+ const meta =
67
+ status === 'error'
68
+ ? (errorMessage ?? 'Failed')
69
+ : status === 'uploading'
70
+ ? 'Uploading…'
71
+ : formatFileSize(sizeInBytes)
72
+
73
+ const body: ReactNode = (
74
+ <>
75
+ <Icon
76
+ className={cn('size-3.5 shrink-0 text-ink-3', status === 'uploading' && 'animate-spin')}
77
+ aria-hidden
78
+ />
79
+ <span className="min-w-0 truncate">{name}</span>
80
+ {meta ? (
81
+ <span className={cn('shrink-0', status !== 'error' && 'text-ink-4')}>{meta}</span>
82
+ ) : null}
83
+ </>
84
+ )
85
+
86
+ return (
87
+ <span
88
+ className={cn(attachmentChipStyles({ status, isInteractive: Boolean(onPress) }), className)}
89
+ title={errorMessage ?? name}
90
+ >
91
+ {onPress ? (
92
+ <button
93
+ type="button"
94
+ onClick={onPress}
95
+ className="inline-flex min-w-0 cursor-pointer items-center gap-1.5 outline-none focus-visible:shadow-[var(--shadow-focus)]"
96
+ >
97
+ {body}
98
+ </button>
99
+ ) : (
100
+ <span className="inline-flex min-w-0 items-center gap-1.5">{body}</span>
101
+ )}
102
+ {onRemove ? (
103
+ <button
104
+ type="button"
105
+ aria-label={`Remove ${name}`}
106
+ onClick={(event) => {
107
+ event.stopPropagation()
108
+ onRemove()
109
+ }}
110
+ className={cn(
111
+ 'inline-flex shrink-0 items-center justify-center',
112
+ 'size-4 rounded-[3px]',
113
+ 'cursor-pointer text-ink-3 hover:bg-surface-3 hover:text-ink',
114
+ 'outline-none focus-visible:shadow-[var(--shadow-focus)]',
115
+ )}
116
+ >
117
+ <svg aria-hidden viewBox="0 0 10 10" className="size-2.5" fill="none">
118
+ <path
119
+ d="M2 2l6 6M8 2l-6 6"
120
+ stroke="currentColor"
121
+ strokeWidth="1.4"
122
+ strokeLinecap="round"
123
+ />
124
+ </svg>
125
+ </button>
126
+ ) : null}
127
+ </span>
128
+ )
129
+ }
@@ -0,0 +1,2 @@
1
+ export type { AttachmentChipProps, AttachmentChipVariants } from './attachment-chip'
2
+ export { AttachmentChip, attachmentChipStyles } from './attachment-chip'
@@ -0,0 +1,70 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+
3
+ import { type AttributeType, AttributeTypeIcon } from './attribute-type-icon'
4
+
5
+ const meta: Meta<typeof AttributeTypeIcon> = {
6
+ title: 'Components/AttributeTypeIcon',
7
+ component: AttributeTypeIcon,
8
+ tags: ['autodocs'],
9
+ args: {
10
+ type: 'string',
11
+ },
12
+ argTypes: {
13
+ type: {
14
+ control: { type: 'inline-radio' },
15
+ options: ['string', 'number', 'integer', 'datetime', 'enum', 'boolean', 'array', 'object'],
16
+ },
17
+ },
18
+ }
19
+
20
+ export default meta
21
+ type Story = StoryObj<typeof AttributeTypeIcon>
22
+
23
+ export const Playground: Story = {}
24
+
25
+ const ALL_TYPES: AttributeType[] = [
26
+ 'string',
27
+ 'number',
28
+ 'integer',
29
+ 'datetime',
30
+ 'enum',
31
+ 'boolean',
32
+ 'array',
33
+ 'object',
34
+ ]
35
+
36
+ export const AllTypes: Story = {
37
+ parameters: { controls: { hideNoControlsWarning: true } },
38
+ render: () => (
39
+ <div className="grid grid-cols-4 gap-3">
40
+ {ALL_TYPES.map((t) => (
41
+ <div
42
+ key={t}
43
+ className="flex items-center gap-2 px-3 py-2 rounded-md border border-rule bg-surface"
44
+ >
45
+ <AttributeTypeIcon type={t} className="size-4 text-ink-3" />
46
+ <span className="font-mono text-[12px] text-ink-2">{t}</span>
47
+ </div>
48
+ ))}
49
+ </div>
50
+ ),
51
+ }
52
+
53
+ export const InChipContext: Story = {
54
+ parameters: { controls: { hideNoControlsWarning: true } },
55
+ render: () => (
56
+ <div className="flex flex-wrap items-center gap-2">
57
+ {ALL_TYPES.map((t) => (
58
+ <span
59
+ key={t}
60
+ className="inline-flex items-center gap-1.5 pl-2 pr-2.5 py-1 rounded-sm border border-rule bg-surface font-sans text-[12.5px] text-ink"
61
+ >
62
+ <span className="text-ink-3">
63
+ <AttributeTypeIcon type={t} />
64
+ </span>
65
+ {t === 'datetime' ? 'created at' : t === 'enum' ? 'status' : t}
66
+ </span>
67
+ ))}
68
+ </div>
69
+ ),
70
+ }
@@ -0,0 +1,125 @@
1
+ import {
2
+ Banknote,
3
+ BookText,
4
+ Braces,
5
+ Brackets,
6
+ Calendar,
7
+ CircleDot,
8
+ Hash,
9
+ Link2,
10
+ type LucideIcon,
11
+ type LucideProps,
12
+ Paperclip,
13
+ ToggleLeft,
14
+ Type,
15
+ User,
16
+ } from 'lucide-react'
17
+ import { cn } from '../../lib/cn'
18
+
19
+ /* =========================================================================
20
+ AttributeTypeIcon — one lucide-react glyph per attribute type. Generic
21
+ over the lib so any attribute-aware UI (filter chips, attribute pickers,
22
+ schema editors, table headers, etc.) can render a consistent icon for
23
+ the same type without re-inventing the mapping.
24
+
25
+ Four exports:
26
+
27
+ - `AttributeType` — the canonical union of attribute-type
28
+ literals.
29
+ - `ATTRIBUTE_TYPE_ICONS` — `Record<AttributeType, LucideIcon>` for
30
+ direct lookups (e.g. when a consumer wants
31
+ the icon component itself, not a rendered
32
+ element).
33
+ - `useAttributeTypeIcon` — hook returning the matching `LucideIcon`.
34
+ Useful when you need to compose the icon
35
+ into a different layout (sized via
36
+ parent's prop, wrapped in a button, etc.).
37
+ - `AttributeTypeIcon` — convenience component with sane defaults
38
+ (`size-3.5`, `aria-hidden`,
39
+ `currentColor`).
40
+
41
+ Mapping
42
+ string → Type ("Aa" lowercase/uppercase glyph)
43
+ number → Hash ("#")
44
+ integer → Hash (same — they're conceptually one bucket)
45
+ datetime → Calendar
46
+ enum → CircleDot (filled-center radio metaphor)
47
+ boolean → ToggleLeft (toggle switch)
48
+ array → Brackets ("[ ]")
49
+ object → Braces ("{ }")
50
+ relation → Link2 (chain link — foreign-key reference)
51
+ user → User (person glyph — platform-user reference)
52
+ currency → Banknote (money — amount + currency_code)
53
+ knowledge-text → BookText (long text stored as a knowledge node)
54
+ file → Paperclip (attachment — stored-file reference)
55
+ ========================================================================= */
56
+
57
+ /**
58
+ * Attribute-type values the design system knows how to render. Exported as a
59
+ * value (an enum-like const object) so consumers can both reference a single
60
+ * member by name (`AttributeType.String`) and iterate the full set
61
+ * (`Object.values(AttributeType)`) without re-declaring the list. The
62
+ * matching type — derived from this same object — keeps the union and the
63
+ * runtime list in lockstep: adding a member here surfaces it in every
64
+ * consumer (icon mapping, type picker, designer config) automatically.
65
+ */
66
+ export const AttributeType = {
67
+ String: 'string',
68
+ Number: 'number',
69
+ Integer: 'integer',
70
+ Datetime: 'datetime',
71
+ Enum: 'enum',
72
+ Boolean: 'boolean',
73
+ Array: 'array',
74
+ Object: 'object',
75
+ Relation: 'relation',
76
+ User: 'user',
77
+ Currency: 'currency',
78
+ KnowledgeText: 'knowledge-text',
79
+ File: 'file',
80
+ } as const
81
+ export type AttributeType = (typeof AttributeType)[keyof typeof AttributeType]
82
+
83
+ /** Iteration order for type pickers, dropdowns, etc. */
84
+ export const ATTRIBUTE_TYPES: ReadonlyArray<AttributeType> = Object.values(AttributeType)
85
+
86
+ export const ATTRIBUTE_TYPE_ICONS: Record<AttributeType, LucideIcon> = {
87
+ [AttributeType.String]: Type,
88
+ [AttributeType.Number]: Hash,
89
+ [AttributeType.Integer]: Hash,
90
+ [AttributeType.Datetime]: Calendar,
91
+ [AttributeType.Enum]: CircleDot,
92
+ [AttributeType.Boolean]: ToggleLeft,
93
+ [AttributeType.Array]: Brackets,
94
+ [AttributeType.Object]: Braces,
95
+ [AttributeType.Relation]: Link2,
96
+ [AttributeType.User]: User,
97
+ [AttributeType.Currency]: Banknote,
98
+ [AttributeType.KnowledgeText]: BookText,
99
+ [AttributeType.File]: Paperclip,
100
+ }
101
+
102
+ export function useAttributeTypeIcon(type: AttributeType): LucideIcon {
103
+ return ATTRIBUTE_TYPE_ICONS[type]
104
+ }
105
+
106
+ export type AttributeTypeIconProps = Omit<LucideProps, 'ref'> & {
107
+ type: AttributeType
108
+ }
109
+
110
+ export function AttributeTypeIcon({
111
+ type,
112
+ className,
113
+ strokeWidth,
114
+ ...props
115
+ }: AttributeTypeIconProps) {
116
+ const Icon = useAttributeTypeIcon(type)
117
+ return (
118
+ <Icon
119
+ aria-hidden
120
+ strokeWidth={strokeWidth ?? 1.6}
121
+ className={cn('size-3.5', className)}
122
+ {...props}
123
+ />
124
+ )
125
+ }
@@ -0,0 +1,8 @@
1
+ export {
2
+ ATTRIBUTE_TYPE_ICONS,
3
+ ATTRIBUTE_TYPES,
4
+ AttributeType,
5
+ AttributeTypeIcon,
6
+ type AttributeTypeIconProps,
7
+ useAttributeTypeIcon,
8
+ } from './attribute-type-icon'