@open-mercato/ui 0.6.7-develop.6860.1.f796b22e80 → 0.6.7

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 (167) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +2 -4
  3. package/agentic/standalone-guide.md +1 -1
  4. package/build.mjs +54 -2
  5. package/dist/ai/AiChat.js +2 -21
  6. package/dist/ai/AiChat.js.map +2 -2
  7. package/dist/backend/AppShell.js +4 -43
  8. package/dist/backend/AppShell.js.map +2 -2
  9. package/dist/backend/AuthSessionGuard.js +0 -14
  10. package/dist/backend/AuthSessionGuard.js.map +2 -2
  11. package/dist/backend/BackendChromeProvider.js +1 -6
  12. package/dist/backend/BackendChromeProvider.js.map +2 -2
  13. package/dist/backend/CrudForm.js +4 -6
  14. package/dist/backend/CrudForm.js.map +2 -2
  15. package/dist/backend/DataTable.js +18 -20
  16. package/dist/backend/DataTable.js.map +2 -2
  17. package/dist/backend/JsonBuilder.js +3 -3
  18. package/dist/backend/JsonBuilder.js.map +2 -2
  19. package/dist/backend/NextStepCallout.js +4 -4
  20. package/dist/backend/NextStepCallout.js.map +1 -1
  21. package/dist/backend/ProfileDropdown.js +1 -2
  22. package/dist/backend/ProfileDropdown.js.map +2 -2
  23. package/dist/backend/RowActions.js +2 -2
  24. package/dist/backend/RowActions.js.map +2 -2
  25. package/dist/backend/confirm-dialog/ConfirmDialog.js +1 -13
  26. package/dist/backend/confirm-dialog/ConfirmDialog.js.map +2 -2
  27. package/dist/backend/crud/useGroupOrder.js +21 -14
  28. package/dist/backend/crud/useGroupOrder.js.map +2 -2
  29. package/dist/backend/detail/AddressTiles.js +5 -4
  30. package/dist/backend/detail/AddressTiles.js.map +2 -2
  31. package/dist/backend/detail/AttachmentDeleteDialog.js +1 -1
  32. package/dist/backend/detail/AttachmentDeleteDialog.js.map +2 -2
  33. package/dist/backend/detail/AttachmentMetadataDialog.js.map +1 -1
  34. package/dist/backend/detail/AttachmentsSection.js +1 -1
  35. package/dist/backend/detail/AttachmentsSection.js.map +2 -2
  36. package/dist/backend/detail/NotesSection.js +1 -1
  37. package/dist/backend/detail/NotesSection.js.map +2 -2
  38. package/dist/backend/detail/TagsSection.js +1 -1
  39. package/dist/backend/detail/TagsSection.js.map +2 -2
  40. package/dist/backend/forms/FormHeader.js +2 -1
  41. package/dist/backend/forms/FormHeader.js.map +2 -2
  42. package/dist/backend/icons/lucideRegistry.generated.js +25 -1
  43. package/dist/backend/icons/lucideRegistry.generated.js.map +2 -2
  44. package/dist/backend/icons/lucideRegistry.js +3 -3
  45. package/dist/backend/icons/lucideRegistry.js.map +2 -2
  46. package/dist/backend/injection/spotIds.js +18 -23
  47. package/dist/backend/injection/spotIds.js.map +2 -2
  48. package/dist/backend/schedule/ScheduleAgenda.js +3 -3
  49. package/dist/backend/schedule/ScheduleAgenda.js.map +1 -1
  50. package/dist/backend/schedule/ScheduleGrid.js +3 -3
  51. package/dist/backend/schedule/ScheduleGrid.js.map +1 -1
  52. package/dist/backend/schedule/ScheduleToolbar.js +70 -87
  53. package/dist/backend/schedule/ScheduleToolbar.js.map +2 -2
  54. package/dist/backend/sidebar/SidebarCustomizationEditor.js +2 -30
  55. package/dist/backend/sidebar/SidebarCustomizationEditor.js.map +2 -2
  56. package/dist/backend/sidebar/customization-helpers.js +0 -30
  57. package/dist/backend/sidebar/customization-helpers.js.map +2 -2
  58. package/dist/backend/utils/api.js +13 -3
  59. package/dist/backend/utils/api.js.map +2 -2
  60. package/dist/backend/utils/apiCall.js +1 -21
  61. package/dist/backend/utils/apiCall.js.map +2 -2
  62. package/dist/backend/utils/customFieldDefs.js.map +2 -2
  63. package/dist/backend/utils/customFieldForms.js +9 -10
  64. package/dist/backend/utils/customFieldForms.js.map +2 -2
  65. package/dist/backend/utils/nav.js +2 -5
  66. package/dist/backend/utils/nav.js.map +2 -2
  67. package/dist/frontend/LanguageSwitcher.js +1 -2
  68. package/dist/frontend/LanguageSwitcher.js.map +2 -2
  69. package/dist/portal/PortalContext.js +1 -1
  70. package/dist/portal/PortalContext.js.map +2 -2
  71. package/dist/portal/hooks/usePortalEventBridge.js +0 -6
  72. package/dist/portal/hooks/usePortalEventBridge.js.map +2 -2
  73. package/dist/portal/hooks/usePortalNotifications.js +4 -42
  74. package/dist/portal/hooks/usePortalNotifications.js.map +2 -2
  75. package/dist/portal/utils/nav.js +3 -2
  76. package/dist/portal/utils/nav.js.map +2 -2
  77. package/dist/primitives/button.js +4 -9
  78. package/dist/primitives/button.js.map +2 -2
  79. package/jest.config.cjs +1 -2
  80. package/package.json +18 -21
  81. package/src/ai/AiChat.tsx +1 -30
  82. package/src/ai/__tests__/AiChat.test.tsx +0 -31
  83. package/src/backend/AppShell.tsx +4 -55
  84. package/src/backend/AuthSessionGuard.tsx +0 -29
  85. package/src/backend/BackendChromeProvider.tsx +1 -19
  86. package/src/backend/CrudForm.tsx +4 -18
  87. package/src/backend/DataTable.tsx +19 -36
  88. package/src/backend/JsonBuilder.tsx +3 -3
  89. package/src/backend/NextStepCallout.tsx +4 -4
  90. package/src/backend/ProfileDropdown.tsx +0 -1
  91. package/src/backend/RowActions.tsx +2 -2
  92. package/src/backend/__tests__/AppShell.test.tsx +7 -65
  93. package/src/backend/__tests__/AuthSessionGuard.test.tsx +0 -52
  94. package/src/backend/__tests__/BackendChromeProvider.test.tsx +2 -98
  95. package/src/backend/__tests__/DataTable.perspectiveStorage.test.ts +1 -62
  96. package/src/backend/__tests__/nav-utils.test.ts +0 -139
  97. package/src/backend/confirm-dialog/ConfirmDialog.tsx +1 -16
  98. package/src/backend/confirm-dialog/__tests__/ConfirmDialog.test.tsx +1 -68
  99. package/src/backend/crud/__tests__/useGroupOrder.test.ts +1 -39
  100. package/src/backend/crud/useGroupOrder.ts +25 -30
  101. package/src/backend/detail/AddressTiles.tsx +6 -3
  102. package/src/backend/detail/AttachmentDeleteDialog.tsx +1 -1
  103. package/src/backend/detail/AttachmentMetadataDialog.tsx +1 -1
  104. package/src/backend/detail/AttachmentsSection.tsx +1 -1
  105. package/src/backend/detail/NotesSection.tsx +1 -1
  106. package/src/backend/detail/TagsSection.tsx +1 -1
  107. package/src/backend/detail/__tests__/AttachmentAssignmentsEditor.test.tsx +0 -21
  108. package/src/backend/forms/FormHeader.tsx +2 -1
  109. package/src/backend/icons/lucideRegistry.generated.tsx +37 -3
  110. package/src/backend/icons/lucideRegistry.ts +2 -2
  111. package/src/backend/injection/spotIds.ts +18 -23
  112. package/src/backend/schedule/ScheduleAgenda.tsx +3 -3
  113. package/src/backend/schedule/ScheduleGrid.tsx +3 -3
  114. package/src/backend/schedule/ScheduleToolbar.tsx +68 -89
  115. package/src/backend/sidebar/SidebarCustomizationEditor.tsx +3 -42
  116. package/src/backend/sidebar/customization-helpers.ts +0 -47
  117. package/src/backend/utils/__tests__/api.test.ts +27 -0
  118. package/src/backend/utils/__tests__/apiCall.test.ts +0 -61
  119. package/src/backend/utils/api.ts +20 -3
  120. package/src/backend/utils/apiCall.ts +1 -29
  121. package/src/backend/utils/customFieldDefs.ts +0 -1
  122. package/src/backend/utils/customFieldForms.ts +11 -15
  123. package/src/backend/utils/nav.ts +2 -22
  124. package/src/frontend/LanguageSwitcher.tsx +0 -1
  125. package/src/portal/PortalContext.tsx +1 -1
  126. package/src/portal/hooks/usePortalEventBridge.ts +0 -6
  127. package/src/portal/hooks/usePortalNotifications.ts +12 -55
  128. package/src/portal/utils/__tests__/nav.test.ts +2 -2
  129. package/src/portal/utils/nav.ts +4 -3
  130. package/src/primitives/button.tsx +4 -10
  131. package/dist/backend/icons/lucideRegistryRuntime.js +0 -28
  132. package/dist/backend/icons/lucideRegistryRuntime.js.map +0 -7
  133. package/dist/backend/perspectiveState.js +0 -34
  134. package/dist/backend/perspectiveState.js.map +0 -7
  135. package/dist/backend/utils/fetchAllPages.js +0 -57
  136. package/dist/backend/utils/fetchAllPages.js.map +0 -7
  137. package/dist/portal/hooks/portalBridgeStatus.js +0 -25
  138. package/dist/portal/hooks/portalBridgeStatus.js.map +0 -7
  139. package/figma/alert.figma.tsx +0 -35
  140. package/figma/badge.figma.tsx +0 -33
  141. package/figma/button.figma.tsx +0 -33
  142. package/figma/checkbox.figma.tsx +0 -28
  143. package/figma/drawer.figma.tsx +0 -40
  144. package/figma/input-variants.figma.tsx +0 -58
  145. package/figma/radio.figma.tsx +0 -16
  146. package/figma/select.figma.tsx +0 -24
  147. package/figma/status-badge.figma.tsx +0 -24
  148. package/figma/switch.figma.tsx +0 -28
  149. package/figma/tabs.figma.tsx +0 -22
  150. package/figma/tag.figma.tsx +0 -27
  151. package/figma.config.json +0 -6
  152. package/scripts/lucideRegistrySource.cjs +0 -133
  153. package/src/backend/__tests__/CrudForm.fieldsetBinding.test.tsx +0 -158
  154. package/src/backend/__tests__/CrudForm.groupInjectionColumn.test.tsx +0 -98
  155. package/src/backend/__tests__/DataTable.metaHiddenLateColumns.test.tsx +0 -105
  156. package/src/backend/icons/__tests__/lucideRegistryGenerator.test.ts +0 -177
  157. package/src/backend/icons/lucideRegistryRuntime.tsx +0 -36
  158. package/src/backend/injection/__tests__/spotIds.extension-points.test.ts +0 -38
  159. package/src/backend/perspectiveState.ts +0 -44
  160. package/src/backend/sidebar/__tests__/group-visibility.test.ts +0 -131
  161. package/src/backend/utils/__tests__/customFieldForms.optionsPaging.test.ts +0 -95
  162. package/src/backend/utils/__tests__/fetchAllPages.test.ts +0 -103
  163. package/src/backend/utils/fetchAllPages.ts +0 -93
  164. package/src/portal/hooks/__tests__/usePortalEventBridge.test.tsx +0 -66
  165. package/src/portal/hooks/__tests__/usePortalNotifications.test.tsx +0 -155
  166. package/src/portal/hooks/portalBridgeStatus.ts +0 -29
  167. package/src/primitives/__tests__/button.test.tsx +0 -70
@@ -1,35 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Alert, AlertDescription, AlertTitle } from '../src/primitives/alert'
4
-
5
- figma.connect(Alert, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=169-2358', {
6
- imports: ["import { Alert, AlertTitle, AlertDescription } from '@open-mercato/ui/primitives/alert'"],
7
- props: {
8
- status: figma.enum('Status', {
9
- Error: 'error',
10
- Warning: 'warning',
11
- Success: 'success',
12
- Information: 'information',
13
- Feature: 'feature',
14
- }),
15
- style: figma.enum('Style', {
16
- Filled: 'filled',
17
- Light: 'light',
18
- Lighter: 'lighter',
19
- Stroke: 'stroke',
20
- }),
21
- size: figma.enum('Size', {
22
- XS: 'xs',
23
- Small: 'sm',
24
- Default: 'default',
25
- }),
26
- title: figma.string('Title'),
27
- description: figma.string('Description'),
28
- },
29
- example: ({ status, style, size, title, description }) => (
30
- <Alert status={status} style={style} size={size}>
31
- <AlertTitle>{title}</AlertTitle>
32
- <AlertDescription>{description}</AlertDescription>
33
- </Alert>
34
- ),
35
- })
@@ -1,33 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Badge } from '../src/primitives/badge'
4
-
5
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
6
- figma.connect(Badge, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
7
- imports: ["import { Badge } from '@open-mercato/ui/primitives/badge'"],
8
- props: {
9
- variant: figma.enum('Variant', {
10
- Default: 'default',
11
- Secondary: 'secondary',
12
- Outline: 'outline',
13
- Muted: 'muted',
14
- Success: 'success',
15
- Warning: 'warning',
16
- Info: 'info',
17
- Neutral: 'neutral',
18
- Error: 'error',
19
- Brand: 'brand',
20
- }),
21
- size: figma.enum('Size', {
22
- Small: 'sm',
23
- Default: 'default',
24
- Large: 'lg',
25
- }),
26
- label: figma.string('Label'),
27
- },
28
- example: ({ variant, size, label }) => (
29
- <Badge variant={variant} size={size}>
30
- {label}
31
- </Badge>
32
- ),
33
- })
@@ -1,33 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Button } from '../src/primitives/button'
4
-
5
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
6
- figma.connect(Button, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
7
- imports: ["import { Button } from '@open-mercato/ui/primitives/button'"],
8
- props: {
9
- variant: figma.enum('Variant', {
10
- Primary: 'default',
11
- Destructive: 'destructive',
12
- Outline: 'outline',
13
- Secondary: 'secondary',
14
- Ghost: 'ghost',
15
- Muted: 'muted',
16
- Link: 'link',
17
- }),
18
- size: figma.enum('Size', {
19
- Default: 'default',
20
- Small: 'sm',
21
- Large: 'lg',
22
- '2XS': '2xs',
23
- Icon: 'icon',
24
- }),
25
- disabled: figma.boolean('Disabled'),
26
- label: figma.string('Label'),
27
- },
28
- example: ({ variant, size, disabled, label }) => (
29
- <Button variant={variant} size={size} disabled={disabled}>
30
- {label}
31
- </Button>
32
- ),
33
- })
@@ -1,28 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Checkbox } from '../src/primitives/checkbox'
4
- import { CheckboxField } from '../src/primitives/checkbox-field'
5
-
6
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
7
- figma.connect(Checkbox, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
8
- imports: ["import { Checkbox } from '@open-mercato/ui/primitives/checkbox'"],
9
- variant: { Label: 'False' },
10
- props: {
11
- checked: figma.boolean('Checked'),
12
- disabled: figma.boolean('Disabled'),
13
- },
14
- example: ({ checked, disabled }) => <Checkbox checked={checked} disabled={disabled} />,
15
- })
16
-
17
- figma.connect(CheckboxField, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
18
- imports: ["import { CheckboxField } from '@open-mercato/ui/primitives/checkbox-field'"],
19
- variant: { Label: 'True' },
20
- props: {
21
- checked: figma.boolean('Checked'),
22
- disabled: figma.boolean('Disabled'),
23
- label: figma.string('Label text'),
24
- },
25
- example: ({ checked, disabled, label }) => (
26
- <CheckboxField checked={checked} disabled={disabled} label={label} />
27
- ),
28
- })
@@ -1,40 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import {
4
- Drawer,
5
- DrawerBody,
6
- DrawerClose,
7
- DrawerContent,
8
- DrawerDescription,
9
- DrawerFooter,
10
- DrawerHeader,
11
- DrawerTitle,
12
- } from '../src/primitives/drawer'
13
- import { Button } from '../src/primitives/button'
14
-
15
- figma.connect(Drawer, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=486-7366', {
16
- imports: [
17
- "import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerBody, DrawerFooter, DrawerClose } from '@open-mercato/ui/primitives/drawer'",
18
- ],
19
- props: {
20
- title: figma.string('Title'),
21
- description: figma.string('Description'),
22
- },
23
- example: ({ title, description }) => (
24
- <Drawer>
25
- <DrawerContent>
26
- <DrawerHeader>
27
- <DrawerTitle>{title}</DrawerTitle>
28
- <DrawerDescription>{description}</DrawerDescription>
29
- </DrawerHeader>
30
- <DrawerBody>Content</DrawerBody>
31
- <DrawerFooter layout="equal">
32
- <DrawerClose asChild>
33
- <Button variant="outline">Cancel</Button>
34
- </DrawerClose>
35
- <Button>Save</Button>
36
- </DrawerFooter>
37
- </DrawerContent>
38
- </Drawer>
39
- ),
40
- })
@@ -1,58 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Input } from '../src/primitives/input'
4
- import { EmailInput } from '../src/primitives/email-input'
5
- import { SearchInput } from '../src/primitives/search-input'
6
- import { PasswordInput } from '../src/primitives/password-input'
7
- import { WebsiteInput } from '../src/primitives/website-input'
8
-
9
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
10
- figma.connect(Input, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
11
- imports: ["import { Input } from '@open-mercato/ui/primitives/input'"],
12
- variant: { Type: 'Text' },
13
- props: {
14
- placeholder: figma.string('Placeholder'),
15
- disabled: figma.boolean('Disabled'),
16
- },
17
- example: ({ placeholder, disabled }) => <Input placeholder={placeholder} disabled={disabled} />,
18
- })
19
-
20
- figma.connect(EmailInput, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
21
- imports: ["import { EmailInput } from '@open-mercato/ui/primitives/email-input'"],
22
- variant: { Type: 'Email' },
23
- props: {
24
- placeholder: figma.string('Placeholder'),
25
- disabled: figma.boolean('Disabled'),
26
- },
27
- example: ({ placeholder, disabled }) => <EmailInput placeholder={placeholder} disabled={disabled} />,
28
- })
29
-
30
- figma.connect(SearchInput, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
31
- imports: ["import { SearchInput } from '@open-mercato/ui/primitives/search-input'"],
32
- variant: { Type: 'Search' },
33
- props: {
34
- placeholder: figma.string('Placeholder'),
35
- disabled: figma.boolean('Disabled'),
36
- },
37
- example: ({ placeholder, disabled }) => <SearchInput placeholder={placeholder} disabled={disabled} />,
38
- })
39
-
40
- figma.connect(PasswordInput, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
41
- imports: ["import { PasswordInput } from '@open-mercato/ui/primitives/password-input'"],
42
- variant: { Type: 'Password' },
43
- props: {
44
- placeholder: figma.string('Placeholder'),
45
- disabled: figma.boolean('Disabled'),
46
- },
47
- example: ({ placeholder, disabled }) => <PasswordInput placeholder={placeholder} disabled={disabled} />,
48
- })
49
-
50
- figma.connect(WebsiteInput, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
51
- imports: ["import { WebsiteInput } from '@open-mercato/ui/primitives/website-input'"],
52
- variant: { Type: 'Website' },
53
- props: {
54
- placeholder: figma.string('Placeholder'),
55
- disabled: figma.boolean('Disabled'),
56
- },
57
- example: ({ placeholder, disabled }) => <WebsiteInput placeholder={placeholder} disabled={disabled} />,
58
- })
@@ -1,16 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Radio, RadioGroup } from '../src/primitives/radio'
4
-
5
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
6
- figma.connect(Radio, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
7
- imports: ["import { Radio, RadioGroup } from '@open-mercato/ui/primitives/radio'"],
8
- props: {
9
- disabled: figma.boolean('Disabled'),
10
- },
11
- example: ({ disabled }) => (
12
- <RadioGroup defaultValue="first">
13
- <Radio value="first" disabled={disabled} />
14
- </RadioGroup>
15
- ),
16
- })
@@ -1,24 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../src/primitives/select'
4
-
5
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
6
- figma.connect(Select, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
7
- imports: [
8
- "import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@open-mercato/ui/primitives/select'",
9
- ],
10
- props: {
11
- placeholder: figma.string('Placeholder'),
12
- disabled: figma.boolean('Disabled'),
13
- },
14
- example: ({ placeholder, disabled }) => (
15
- <Select>
16
- <SelectTrigger disabled={disabled}>
17
- <SelectValue placeholder={placeholder} />
18
- </SelectTrigger>
19
- <SelectContent>
20
- <SelectItem value="first">First option</SelectItem>
21
- </SelectContent>
22
- </Select>
23
- ),
24
- })
@@ -1,24 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { StatusBadge } from '../src/primitives/status-badge'
4
-
5
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
6
- figma.connect(StatusBadge, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
7
- imports: ["import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'"],
8
- props: {
9
- variant: figma.enum('Variant', {
10
- Success: 'success',
11
- Warning: 'warning',
12
- Error: 'error',
13
- Info: 'info',
14
- Neutral: 'neutral',
15
- }),
16
- dot: figma.boolean('Dot'),
17
- label: figma.string('Label'),
18
- },
19
- example: ({ variant, dot, label }) => (
20
- <StatusBadge variant={variant} dot={dot}>
21
- {label}
22
- </StatusBadge>
23
- ),
24
- })
@@ -1,28 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Switch } from '../src/primitives/switch'
4
- import { SwitchField } from '../src/primitives/switch-field'
5
-
6
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
7
- figma.connect(Switch, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
8
- imports: ["import { Switch } from '@open-mercato/ui/primitives/switch'"],
9
- variant: { Label: 'False' },
10
- props: {
11
- checked: figma.boolean('Checked'),
12
- disabled: figma.boolean('Disabled'),
13
- },
14
- example: ({ checked, disabled }) => <Switch checked={checked} disabled={disabled} />,
15
- })
16
-
17
- figma.connect(SwitchField, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
18
- imports: ["import { SwitchField } from '@open-mercato/ui/primitives/switch-field'"],
19
- variant: { Label: 'True' },
20
- props: {
21
- checked: figma.boolean('Checked'),
22
- disabled: figma.boolean('Disabled'),
23
- label: figma.string('Label text'),
24
- },
25
- example: ({ checked, disabled, label }) => (
26
- <SwitchField checked={checked} disabled={disabled} label={label} />
27
- ),
28
- })
@@ -1,22 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Tabs, TabsContent, TabsList, TabsTrigger } from '../src/primitives/tabs'
4
-
5
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
6
- figma.connect(Tabs, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
7
- imports: ["import { Tabs, TabsList, TabsTrigger, TabsContent } from '@open-mercato/ui/primitives/tabs'"],
8
- props: {
9
- label: figma.string('Label'),
10
- count: figma.string('Count'),
11
- },
12
- example: ({ label, count }) => (
13
- <Tabs defaultValue="first" variant="underline">
14
- <TabsList aria-label="Sections">
15
- <TabsTrigger value="first" count={count}>
16
- {label}
17
- </TabsTrigger>
18
- </TabsList>
19
- <TabsContent value="first">Content</TabsContent>
20
- </Tabs>
21
- ),
22
- })
@@ -1,27 +0,0 @@
1
- import React from 'react'
2
- import figma from '@figma/code-connect'
3
- import { Tag } from '../src/primitives/tag'
4
-
5
- // TODO(figma): resolve the real node id in the DS file before ds:code-connect:publish.
6
- figma.connect(Tag, 'https://www.figma.com/design/qCq9z6q1if0mpoRstV5OEA/Design-System?node-id=0-1', {
7
- imports: ["import { Tag } from '@open-mercato/ui/primitives/tag'"],
8
- props: {
9
- variant: figma.enum('Variant', {
10
- Default: 'default',
11
- Success: 'success',
12
- Warning: 'warning',
13
- Error: 'error',
14
- Info: 'info',
15
- Neutral: 'neutral',
16
- Brand: 'brand',
17
- Pink: 'pink',
18
- }),
19
- dot: figma.boolean('Dot'),
20
- label: figma.string('Label'),
21
- },
22
- example: ({ variant, dot, label }) => (
23
- <Tag variant={variant} dot={dot}>
24
- {label}
25
- </Tag>
26
- ),
27
- })
package/figma.config.json DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "codeConnect": {
3
- "parser": "react",
4
- "include": ["figma/**/*.figma.tsx", "src/primitives/**/*.tsx"]
5
- }
6
- }
@@ -1,133 +0,0 @@
1
- // Pure source emitter for src/backend/icons/lucideRegistry.generated.tsx.
2
- // Kept side-effect free, and CommonJS so both build.mjs and the Jest suite can load it.
3
-
4
- const {
5
- IndentationText,
6
- Project,
7
- QuoteKind,
8
- ScriptKind,
9
- StructureKind,
10
- VariableDeclarationKind,
11
- } = require('ts-morph')
12
-
13
- const GENERATED_FILE_NAME = 'lucideRegistry.generated.tsx'
14
- const LUCIDE_MODULE_SPECIFIER = 'lucide-react'
15
- const BANNER = `/* eslint-disable */
16
- // AUTO-GENERATED by @open-mercato/ui build. Do not edit by hand.
17
- // Generated from discovered icon string usages across the repo.
18
-
19
- `
20
-
21
- let sharedProject = null
22
-
23
- function getProject() {
24
- if (!sharedProject) {
25
- sharedProject = new Project({
26
- useInMemoryFileSystem: true,
27
- manipulationSettings: {
28
- indentationText: IndentationText.TwoSpaces,
29
- quoteKind: QuoteKind.Single,
30
- useTrailingCommas: true,
31
- },
32
- })
33
- }
34
-
35
- return sharedProject
36
- }
37
-
38
- function sortResolvedIcons(resolvedIcons) {
39
- return [...resolvedIcons].sort((a, b) => a.kebab.localeCompare(b.kebab))
40
- }
41
-
42
- function collectUniqueExports(resolvedIcons) {
43
- return [...new Set(resolvedIcons.map((icon) => icon.exportName))].sort((a, b) => a.localeCompare(b))
44
- }
45
-
46
- function writeNamedImports(exportNames) {
47
- return (writer) => {
48
- writer.newLine()
49
- for (const name of exportNames) {
50
- writer.write(`${name},`)
51
- writer.newLine()
52
- }
53
- }
54
- }
55
-
56
- function writeRegistryLiteral(entries) {
57
- return (writer) => {
58
- if (entries.length === 0) {
59
- writer.write('{}')
60
- return
61
- }
62
-
63
- writer.write('{')
64
- writer.newLine()
65
- for (const icon of entries) {
66
- writer.write(`'${icon.kebab}': ${icon.exportName},`)
67
- writer.newLine()
68
- }
69
- writer.write('}')
70
- }
71
- }
72
-
73
- function assertNoSyntacticDiagnostics(project, sourceFile) {
74
- const diagnostics = project.getProgram().getSyntacticDiagnostics(sourceFile)
75
- if (diagnostics.length === 0) return
76
-
77
- const details = diagnostics
78
- .map((diagnostic) => ` line ${diagnostic.getLineNumber() ?? 0}: ${diagnostic.getMessageText()}`)
79
- .join('\n')
80
- throw new Error(`[internal] Generated ${GENERATED_FILE_NAME} is not syntactically valid:\n${details}`)
81
- }
82
-
83
- function normalizeSourceText(text) {
84
- const normalized = text.replace(/\r\n/g, '\n')
85
- return normalized.endsWith('\n') ? normalized : `${normalized}\n`
86
- }
87
-
88
- function buildLucideRegistrySource(resolvedIcons) {
89
- const entries = sortResolvedIcons(resolvedIcons)
90
- const uniqueExports = collectUniqueExports(entries)
91
-
92
- const project = getProject()
93
- const sourceFile = project.createSourceFile(GENERATED_FILE_NAME, '', {
94
- overwrite: true,
95
- scriptKind: ScriptKind.TSX,
96
- })
97
-
98
- sourceFile.addImportDeclaration({
99
- kind: StructureKind.ImportDeclaration,
100
- isTypeOnly: true,
101
- namedImports: [{ name: 'LucideIcon' }],
102
- moduleSpecifier: LUCIDE_MODULE_SPECIFIER,
103
- })
104
-
105
- if (uniqueExports.length > 0) {
106
- sourceFile.addImportDeclaration({
107
- kind: StructureKind.ImportDeclaration,
108
- namedImports: writeNamedImports(uniqueExports),
109
- moduleSpecifier: LUCIDE_MODULE_SPECIFIER,
110
- })
111
- }
112
-
113
- sourceFile.addVariableStatement({
114
- kind: StructureKind.VariableStatement,
115
- isExported: true,
116
- declarationKind: VariableDeclarationKind.Const,
117
- declarations: [
118
- {
119
- name: 'LUCIDE_ICON_REGISTRY',
120
- type: 'Record<string, LucideIcon>',
121
- initializer: writeRegistryLiteral(entries),
122
- },
123
- ],
124
- })
125
-
126
- sourceFile.formatText({ indentSize: 2, convertTabsToSpaces: true })
127
- sourceFile.insertText(0, BANNER)
128
- assertNoSyntacticDiagnostics(project, sourceFile)
129
-
130
- return normalizeSourceText(sourceFile.getFullText())
131
- }
132
-
133
- module.exports = { buildLucideRegistrySource }
@@ -1,158 +0,0 @@
1
- /** @jest-environment jsdom */
2
- jest.setTimeout(15000)
3
-
4
- const fetchCustomFieldFormStructureMock = jest.fn()
5
- const buildFormFieldFromCustomFieldDefMock = jest.fn()
6
- const triggerInjectionEventMock = jest.fn(async (_event: string, data: Record<string, unknown>) => ({
7
- ok: true,
8
- data,
9
- }))
10
-
11
- jest.mock('next/navigation', () => ({
12
- useRouter: () => ({ push: jest.fn() }),
13
- usePathname: () => '/',
14
- useSearchParams: () => new URLSearchParams(),
15
- }))
16
- jest.mock('remark-gfm', () => ({ __esModule: true, default: {} }))
17
- jest.mock('../confirm-dialog', () => ({
18
- useConfirmDialog: () => ({
19
- confirm: jest.fn().mockResolvedValue(true),
20
- ConfirmDialogElement: null,
21
- }),
22
- }))
23
- jest.mock('../injection/InjectionSpot', () => ({
24
- __esModule: true,
25
- InjectionSpot: () => null,
26
- useInjectionWidgets: () => ({ widgets: [], loading: false, error: null }),
27
- useInjectionSpotEvents: () => ({ triggerEvent: triggerInjectionEventMock }),
28
- }))
29
- jest.mock('../injection/useInjectionDataWidgets', () => ({
30
- __esModule: true,
31
- useInjectionDataWidgets: () => ({ widgets: [], isLoading: false, error: null }),
32
- }))
33
- jest.mock('../custom-fields/FieldDefinitionsManager', () => {
34
- const React = require('react')
35
- return {
36
- __esModule: true,
37
- FieldDefinitionsManager: React.forwardRef(() => <div>Field definitions manager</div>),
38
- }
39
- })
40
- jest.mock('../utils/customFieldForms', () => ({
41
- __esModule: true,
42
- buildFormFieldFromCustomFieldDef: (...args: unknown[]) => buildFormFieldFromCustomFieldDefMock(...args),
43
- buildFormFieldsFromCustomFields: jest.fn(() => []),
44
- fetchCustomFieldFormStructure: (...args: unknown[]) => fetchCustomFieldFormStructureMock(...args),
45
- }))
46
-
47
- import * as React from 'react'
48
- import { act, waitFor } from '@testing-library/react'
49
- import { renderWithProviders } from '@open-mercato/shared/lib/testing/renderWithProviders'
50
- import { CrudForm, type CrudField, type CrudFormGroup } from '../CrudForm'
51
-
52
- const ENTITY_ID = 'resources:resources_resource'
53
- const GENERAL_CODE = 'resources_resource_general'
54
- const LAPTOP_CODE = 'resources_resource_laptop'
55
-
56
- const fields: CrudField[] = [{ id: 'name', label: 'Name', type: 'text' }]
57
- const groups: CrudFormGroup[] = [
58
- { id: 'details', title: 'Details', fields: ['name'] },
59
- { id: 'custom', title: 'Custom fields', kind: 'customFields' },
60
- ]
61
-
62
- function configureTwoFieldsets() {
63
- buildFormFieldFromCustomFieldDefMock.mockImplementation((definition: any) => ({
64
- id: `cf_${definition.key}`,
65
- label: definition.label ?? definition.key,
66
- type: 'text',
67
- }))
68
- fetchCustomFieldFormStructureMock.mockResolvedValue({
69
- fields: [],
70
- definitions: [
71
- {
72
- entityId: ENTITY_ID,
73
- key: 'asset_tag',
74
- label: 'Asset tag',
75
- kind: 'text',
76
- fieldsets: [GENERAL_CODE],
77
- },
78
- {
79
- entityId: ENTITY_ID,
80
- key: 'serial_number',
81
- label: 'Serial number',
82
- kind: 'text',
83
- fieldsets: [LAPTOP_CODE],
84
- },
85
- ],
86
- metadata: {
87
- items: [],
88
- fieldsetsByEntity: {
89
- [ENTITY_ID]: [
90
- { code: GENERAL_CODE, label: 'General' },
91
- { code: LAPTOP_CODE, label: 'Laptops' },
92
- ],
93
- },
94
- entitySettings: {
95
- [ENTITY_ID]: { singleFieldsetPerRecord: true },
96
- },
97
- },
98
- })
99
- }
100
-
101
- function DelayedHost({
102
- initialValues,
103
- }: {
104
- initialValues: Record<string, unknown> | undefined
105
- }) {
106
- return (
107
- <CrudForm
108
- embedded
109
- title="Resource"
110
- entityId={ENTITY_ID}
111
- fields={fields}
112
- groups={groups}
113
- customFieldsetBindings={{ [ENTITY_ID]: { valueKey: 'customFieldsetCode' } }}
114
- initialValues={initialValues ?? undefined}
115
- isLoading={!initialValues}
116
- onSubmit={() => {}}
117
- />
118
- )
119
- }
120
-
121
- describe('CrudForm customFieldsetBindings hydration', () => {
122
- beforeEach(() => {
123
- fetchCustomFieldFormStructureMock.mockReset()
124
- buildFormFieldFromCustomFieldDefMock.mockReset()
125
- triggerInjectionEventMock.mockClear()
126
- configureTwoFieldsets()
127
- })
128
-
129
- it('activates the persisted fieldset when initialValues arrive after fieldset metadata loads', async () => {
130
- // Mirrors the resources edit page: the record (and its persisted
131
- // customFieldsetCode) loads asynchronously AFTER custom-field metadata has
132
- // already resolved (gated behind resourceTypesLoaded), so the fieldset
133
- // selector is hydrated only via the binding, never via a user interaction.
134
- const { container, rerender } = renderWithProviders(
135
- <DelayedHost initialValues={undefined} />,
136
- { dict: { 'ui.forms.actions.save': 'Save' } },
137
- )
138
-
139
- await waitFor(() => {
140
- expect(fetchCustomFieldFormStructureMock).toHaveBeenCalled()
141
- })
142
-
143
- await act(async () => {
144
- rerender(
145
- <DelayedHost
146
- initialValues={{ id: 'res-1', name: 'Engineering Laptop 1', customFieldsetCode: LAPTOP_CODE }}
147
- />,
148
- )
149
- await Promise.resolve()
150
- await Promise.resolve()
151
- })
152
-
153
- await waitFor(() => {
154
- expect(container.querySelector('[data-crud-field-id="cf_serial_number"]')).not.toBeNull()
155
- })
156
- expect(container.querySelector('[data-crud-field-id="cf_asset_tag"]')).toBeNull()
157
- })
158
- })