@rokkit/core 1.0.0-next.11 → 1.0.0-next.111

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 (87) hide show
  1. package/dist/calendar.d.ts +10 -0
  2. package/dist/colors/index.d.ts +333 -0
  3. package/dist/connector.d.ts +8 -0
  4. package/dist/constants.d.ts +39 -0
  5. package/dist/events.d.ts +12 -0
  6. package/dist/field-mapper.d.ts +63 -0
  7. package/dist/index.d.ts +13 -0
  8. package/dist/key-event-map.d.ts +18 -0
  9. package/dist/mapped-items.d.ts +14 -0
  10. package/dist/mapping.d.ts +75 -0
  11. package/dist/nested.d.ts +18 -0
  12. package/dist/string.d.ts +59 -0
  13. package/dist/theme.d.ts +52 -0
  14. package/dist/ticks.d.ts +10 -0
  15. package/dist/types.d.ts +245 -0
  16. package/dist/utils.d.ts +70 -0
  17. package/package.json +13 -38
  18. package/src/calendar.js +44 -0
  19. package/src/colors/index.js +19 -0
  20. package/src/colors/syntax.json +42 -0
  21. package/src/colors/tailwind.json +289 -0
  22. package/src/connector.js +34 -0
  23. package/src/constants.js +67 -94
  24. package/src/events.js +32 -0
  25. package/src/field-mapper.js +148 -0
  26. package/src/index.js +19 -27
  27. package/src/key-event-map.js +36 -0
  28. package/src/mapped-items.js +22 -0
  29. package/src/mapping.js +134 -0
  30. package/src/nested.js +56 -0
  31. package/src/string.js +97 -0
  32. package/src/theme.js +205 -0
  33. package/src/ticks.js +26 -0
  34. package/src/types.js +124 -0
  35. package/src/utils.js +134 -0
  36. package/LICENSE +0 -21
  37. package/README.md +0 -1
  38. package/src/Accordion.svelte +0 -80
  39. package/src/Alerts.svelte +0 -39
  40. package/src/DropDown.svelte +0 -79
  41. package/src/DropSearch.svelte +0 -67
  42. package/src/Icon.svelte +0 -15
  43. package/src/List-Discard.svelte +0 -48
  44. package/src/List.svelte +0 -65
  45. package/src/ListActions.svelte +0 -35
  46. package/src/NavTabs.svelte +0 -0
  47. package/src/NestedList.svelte +0 -87
  48. package/src/Overlay.svelte +0 -4
  49. package/src/PageNavigator.svelte +0 -94
  50. package/src/ResponsiveGrid.svelte +0 -73
  51. package/src/Scrollable.svelte +0 -8
  52. package/src/Searchable.svelte +0 -19
  53. package/src/Sidebar.svelte +0 -5
  54. package/src/Slider.svelte +0 -17
  55. package/src/SpinList.svelte +0 -48
  56. package/src/SplitPane.svelte +0 -109
  57. package/src/SplitView.svelte +0 -44
  58. package/src/Splitter.svelte +0 -95
  59. package/src/TabItem.svelte +0 -27
  60. package/src/TabItems.svelte +0 -34
  61. package/src/Tabs.svelte +0 -31
  62. package/src/Tree.svelte +0 -19
  63. package/src/actions/dismissable.js +0 -24
  64. package/src/actions/fillable.js +0 -114
  65. package/src/actions/hierarchy.js +0 -189
  66. package/src/actions/index.js +0 -7
  67. package/src/actions/navigable.js +0 -42
  68. package/src/actions/navigator.js +0 -179
  69. package/src/actions/pannable.js +0 -50
  70. package/src/actions/swipeable.js +0 -56
  71. package/src/actions/themeable.js +0 -23
  72. package/src/items/Collapsible.svelte +0 -51
  73. package/src/items/Connector.svelte +0 -26
  74. package/src/items/Link.svelte +0 -17
  75. package/src/items/Node.svelte +0 -52
  76. package/src/items/Pill.svelte +0 -19
  77. package/src/items/Separator.svelte +0 -1
  78. package/src/items/Summary.svelte +0 -27
  79. package/src/items/Text.svelte +0 -21
  80. package/src/items/index.js +0 -8
  81. package/src/list.js +0 -14
  82. package/src/mocks/Custom.svelte +0 -7
  83. package/src/mocks/index.js +0 -10
  84. package/src/stores/alerts.js +0 -3
  85. package/src/stores/index.js +0 -6
  86. package/src/stores/persist.js +0 -63
  87. package/src/stores/theme.js +0 -34
@@ -0,0 +1,289 @@
1
+ {
2
+ "amber": {
3
+ "50": "#fffbeb",
4
+ "100": "#fef3c7",
5
+ "200": "#fde68a",
6
+ "300": "#fcd34d",
7
+ "400": "#fbbf24",
8
+ "500": "#f59e0b",
9
+ "600": "#d97706",
10
+ "700": "#b45309",
11
+ "800": "#92400e",
12
+ "900": "#78350f",
13
+ "950": "#451a03"
14
+ },
15
+ "blue": {
16
+ "50": "#eff6ff",
17
+ "100": "#dbeafe",
18
+ "200": "#bfdbfe",
19
+ "300": "#93c5fd",
20
+ "400": "#60a5fa",
21
+ "500": "#3b82f6",
22
+ "600": "#2563eb",
23
+ "700": "#1d4ed8",
24
+ "800": "#1e40af",
25
+ "900": "#1e3a8a",
26
+ "950": "#172554"
27
+ },
28
+ "cyan": {
29
+ "50": "#ecfeff",
30
+ "100": "#cffafe",
31
+ "200": "#a5f3fc",
32
+ "300": "#67e8f9",
33
+ "400": "#22d3ee",
34
+ "500": "#06b6d4",
35
+ "600": "#0891b2",
36
+ "700": "#0e7490",
37
+ "800": "#155e75",
38
+ "900": "#164e63",
39
+ "950": "#083344"
40
+ },
41
+ "emerald": {
42
+ "50": "#ecfdf5",
43
+ "100": "#d1fae5",
44
+ "200": "#a7f3d0",
45
+ "300": "#6ee7b7",
46
+ "400": "#34d399",
47
+ "500": "#10b981",
48
+ "600": "#059669",
49
+ "700": "#047857",
50
+ "800": "#065f46",
51
+ "900": "#064e3b",
52
+ "950": "#022c22"
53
+ },
54
+ "fuscia": {
55
+ "50": "#fdf4ff",
56
+ "100": "#fae8ff",
57
+ "200": "#f5d0fe",
58
+ "300": "#f0abfc",
59
+ "400": "#e879f9",
60
+ "500": "#d946ef",
61
+ "600": "#c026d3",
62
+ "700": "#a21caf",
63
+ "800": "#86198f",
64
+ "900": "#701a75",
65
+ "950": "#4a044e"
66
+ },
67
+ "gray": {
68
+ "50": "#f9fafb",
69
+ "100": "#f3f4f6",
70
+ "200": "#e5e7eb",
71
+ "300": "#d1d5db",
72
+ "400": "#9ca3af",
73
+ "500": "#6b7280",
74
+ "600": "#4b5563",
75
+ "700": "#374151",
76
+ "800": "#1f2937",
77
+ "900": "#111827",
78
+ "950": "#00060c"
79
+ },
80
+ "green": {
81
+ "50": "#f0fdf4",
82
+ "100": "#dcfce7",
83
+ "200": "#bbf7d0",
84
+ "300": "#86efac",
85
+ "400": "#4ade80",
86
+ "500": "#22c55e",
87
+ "600": "#16a34a",
88
+ "700": "#15803d",
89
+ "800": "#166534",
90
+ "900": "#14532d",
91
+ "950": "#052e16"
92
+ },
93
+ "indigo": {
94
+ "50": "#eef2ff",
95
+ "100": "#e0e7ff",
96
+ "200": "#c7d2fe",
97
+ "300": "#a5b4fc",
98
+ "400": "#818cf8",
99
+ "500": "#6366f1",
100
+ "600": "#4f46e5",
101
+ "700": "#4338ca",
102
+ "800": "#3730a3",
103
+ "900": "#312e81",
104
+ "950": "#1e1b4b"
105
+ },
106
+ "lime": {
107
+ "50": "#f7fee7",
108
+ "100": "#ecfccb",
109
+ "200": "#d9f99d",
110
+ "300": "#bef264",
111
+ "400": "#a3e635",
112
+ "500": "#84cc16",
113
+ "600": "#65a30d",
114
+ "700": "#4d7c0f",
115
+ "800": "#3f6212",
116
+ "900": "#365314",
117
+ "950": "#1a2e05"
118
+ },
119
+ "orange": {
120
+ "50": "#fff7ed",
121
+ "100": "#ffedd5",
122
+ "200": "#fed7aa",
123
+ "300": "#fdba74",
124
+ "400": "#fb923c",
125
+ "500": "#f97316",
126
+ "600": "#ea580c",
127
+ "700": "#c2410c",
128
+ "800": "#9a3412",
129
+ "900": "#7c2d12",
130
+ "950": "#431407"
131
+ },
132
+ "pink": {
133
+ "50": "#fdf2f8",
134
+ "100": "#fce7f3",
135
+ "200": "#fbcfe8",
136
+ "300": "#f9a8d4",
137
+ "400": "#f472b6",
138
+ "500": "#ec4899",
139
+ "600": "#db2777",
140
+ "700": "#be185d",
141
+ "800": "#9d174d",
142
+ "900": "#831843",
143
+ "950": "#500724"
144
+ },
145
+ "purple": {
146
+ "50": "#faf5ff",
147
+ "100": "#f3e8ff",
148
+ "200": "#e9d5ff",
149
+ "300": "#d8b4fe",
150
+ "400": "#c084fc",
151
+ "500": "#a855f7",
152
+ "600": "#9333ea",
153
+ "700": "#7e22ce",
154
+ "800": "#6b21a8",
155
+ "900": "#581c87",
156
+ "950": "#3b0764"
157
+ },
158
+ "red": {
159
+ "50": "#fef2f2",
160
+ "100": "#fee2e2",
161
+ "200": "#fecaca",
162
+ "300": "#fca5a5",
163
+ "400": "#f87171",
164
+ "500": "#ef4444",
165
+ "600": "#dc2626",
166
+ "700": "#b91c1c",
167
+ "800": "#991b1b",
168
+ "900": "#7f1d1d",
169
+ "950": "#450a0a"
170
+ },
171
+ "rose": {
172
+ "50": "#fff1f2",
173
+ "100": "#ffe4e6",
174
+ "200": "#fecdd3",
175
+ "300": "#fda4af",
176
+ "400": "#fb7185",
177
+ "500": "#f43f5e",
178
+ "600": "#e11d48",
179
+ "700": "#be123c",
180
+ "800": "#9f1239",
181
+ "900": "#881337",
182
+ "950": "#4c0519"
183
+ },
184
+ "sky": {
185
+ "50": "#f0f9ff",
186
+ "100": "#e0f2fe",
187
+ "200": "#bae6fd",
188
+ "300": "#7dd3fc",
189
+ "400": "#38bdf8",
190
+ "500": "#0ea5e9",
191
+ "600": "#0284c7",
192
+ "700": "#0369a1",
193
+ "800": "#075985",
194
+ "900": "#0c4a6e",
195
+ "950": "#082f49"
196
+ },
197
+ "slate": {
198
+ "50": "#f8fafc",
199
+ "100": "#f1f5f9",
200
+ "200": "#e2e8f0",
201
+ "300": "#cbd5e0",
202
+ "400": "#94a3b8",
203
+ "500": "#64748b",
204
+ "600": "#475569",
205
+ "700": "#334155",
206
+ "800": "#1e293b",
207
+ "900": "#0f172a",
208
+ "950": "#020617"
209
+ },
210
+ "stone": {
211
+ "50": "#fafaf9",
212
+ "100": "#f5f5f4",
213
+ "200": "#e7e5e4",
214
+ "300": "#d6d3d1",
215
+ "400": "#a8a29e",
216
+ "500": "#78716c",
217
+ "600": "#57534e",
218
+ "700": "#44403c",
219
+ "800": "#292524",
220
+ "900": "#1c1917",
221
+ "950": "#0c0a09"
222
+ },
223
+ "teal": {
224
+ "50": "#f0fdfa",
225
+ "100": "#ccfbf1",
226
+ "200": "#99f6e4",
227
+ "300": "#5eead4",
228
+ "400": "#2dd4bf",
229
+ "500": "#14b8a6",
230
+ "600": "#0d9488",
231
+ "700": "#0f766e",
232
+ "800": "#115e59",
233
+ "900": "#134e4a",
234
+ "950": "#042f2e"
235
+ },
236
+ "violet": {
237
+ "50": "#f5f3ff",
238
+ "100": "#ede9fe",
239
+ "200": "#ddd6fe",
240
+ "300": "#c4b5fd",
241
+ "400": "#a78bfa",
242
+ "500": "#8b5cf6",
243
+ "600": "#7c3aed",
244
+ "700": "#6d28d9",
245
+ "800": "#5b21b6",
246
+ "900": "#4c1d95",
247
+ "950": "#2e1065"
248
+ },
249
+ "yellow": {
250
+ "50": "#fefce8",
251
+ "100": "#fef9c3",
252
+ "200": "#fef08a",
253
+ "300": "#fde047",
254
+ "400": "#facc15",
255
+ "500": "#eab308",
256
+ "600": "#ca8a04",
257
+ "700": "#a16207",
258
+ "800": "#854d0e",
259
+ "900": "#713f12",
260
+ "950": "#422006"
261
+ },
262
+ "zinc": {
263
+ "50": "#fafafa",
264
+ "100": "#f4f4f5",
265
+ "200": "#e4e4e7",
266
+ "300": "#d4d4d8",
267
+ "400": "#a1a1aa",
268
+ "500": "#71717a",
269
+ "600": "#52525b",
270
+ "700": "#3f3f46",
271
+ "800": "#27272a",
272
+ "900": "#18181b",
273
+ "950": "#000000"
274
+ },
275
+ "shark": {
276
+ "DEFAULT": "#677287",
277
+ "50": "#ffffff",
278
+ "100": "#efefef",
279
+ "200": "#E0E0E0",
280
+ "300": "#C1C6D0",
281
+ "400": "#828C9F",
282
+ "500": "#677287",
283
+ "600": "#51596A",
284
+ "700": "#3B414D",
285
+ "800": "#2E323C",
286
+ "900": "#20242A",
287
+ "950": "#1A1C22"
288
+ }
289
+ }
@@ -0,0 +1,34 @@
1
+ const LINE_TYPES = {
2
+ CHILD: 'child',
3
+ LAST: 'last',
4
+ SIBLING: 'sibling',
5
+ EMPTY: 'empty',
6
+ ICON: 'icon'
7
+ }
8
+
9
+ const nextType = {
10
+ [LINE_TYPES.CHILD]: LINE_TYPES.SIBLING,
11
+ [LINE_TYPES.LAST]: LINE_TYPES.EMPTY,
12
+ [LINE_TYPES.SIBLING]: LINE_TYPES.SIBLING,
13
+ [LINE_TYPES.EMPTY]: LINE_TYPES.EMPTY
14
+ }
15
+
16
+ /**
17
+ * Constructs an array of line types for tree visualization
18
+ * @param {boolean} hasChildren - Whether the node has children
19
+ * @param {import('./types').LineType[]} parentTypes - Types from parent nodes
20
+ * @param {import('./types').LineType} position - Current position type
21
+ * @returns {import('./types').LineType[]} Array of line types
22
+ */
23
+ export function getLineTypes(hasChildren = false, parentTypes = [], position = LINE_TYPES.CHILD) {
24
+ return parentTypes
25
+ .reduce((acc, type, index) => {
26
+ // For all but the last parent type, convert to next type
27
+ if (index < parentTypes.length - 1) {
28
+ return [...acc, nextType[type]]
29
+ }
30
+ // For the last parent type, use the position
31
+ return [...acc, position]
32
+ }, [])
33
+ .concat(hasChildren ? LINE_TYPES.ICON : LINE_TYPES.EMPTY)
34
+ }
package/src/constants.js CHANGED
@@ -1,3 +1,34 @@
1
+ export { defaultColors, syntaxColors, shades, defaultPalette } from './colors/index.js'
2
+
3
+ /**
4
+ * @type {import('./types).FieldMapping} Fields
5
+ */
6
+ export const defaultFields = {
7
+ id: 'id',
8
+ url: 'url',
9
+ text: 'text',
10
+ value: 'value',
11
+ children: 'children',
12
+ icon: 'icon',
13
+ iconPrefix: null,
14
+ image: 'image',
15
+ summary: 'summary',
16
+ notes: 'notes',
17
+ props: 'props',
18
+ target: 'target',
19
+ state: 'state',
20
+ level: 'level',
21
+ parent: 'parent',
22
+ currency: 'currency',
23
+ label: 'label',
24
+ component: 'component',
25
+ snippet: '_snippet',
26
+ /* flag fields */
27
+ deleted: '_deleted',
28
+ expanded: '_expanded',
29
+ selected: '_selected'
30
+ }
31
+
1
32
  export const defaultIcons = [
2
33
  'accordion-opened',
3
34
  'accordion-closed',
@@ -6,7 +37,6 @@ export const defaultIcons = [
6
37
  'action-clear',
7
38
  'action-search',
8
39
  'action-close',
9
- 'action-close-filled',
10
40
  'node-opened',
11
41
  'node-closed',
12
42
  'selector-opened',
@@ -16,6 +46,7 @@ export const defaultIcons = [
16
46
  'checkbox-unknown',
17
47
  'rating-filled',
18
48
  'rating-empty',
49
+ 'rating-half',
19
50
  'radio-off',
20
51
  'radio-on',
21
52
  'mode-dark',
@@ -23,39 +54,25 @@ export const defaultIcons = [
23
54
  'navigate-left',
24
55
  'navigate-right',
25
56
  'navigate-up',
26
- 'navigate-down'
57
+ 'navigate-down',
58
+ 'state-error',
59
+ 'state-warning',
60
+ 'state-success',
61
+ 'state-info',
62
+ 'state-unknown',
63
+ 'badge-fail',
64
+ 'badge-warn',
65
+ 'badge-pass',
66
+ 'badge-unknown',
67
+ 'sort-none',
68
+ 'sort-ascending',
69
+ 'sort-descending',
70
+ 'validity-failed',
71
+ 'validity-passed',
72
+ 'validity-unknown',
73
+ 'validity-warning'
27
74
  ]
28
75
 
29
- // export const defaultIcons = [
30
- // 'accordion-opened',
31
- // 'accordion-closed',
32
- // 'action-remove',
33
- // 'action-add',
34
- // 'action-clear',
35
- // 'action-search',
36
- // 'action-close',
37
- // 'node-opened',
38
- // 'node-closed',
39
- // 'checkbox-checked',
40
- // 'checkbox-unchecked',
41
- // 'checkbox-unknown',
42
- // 'rating-filled',
43
- // 'rating-empty',
44
- // 'rating-half',
45
- // 'radio-off',
46
- // 'radio-on',
47
- // 'folder-closed',
48
- // 'folder-opened',
49
- // 'navigate-up',
50
- // 'navigate-down',
51
- // 'navigate-left',
52
- // 'navigate-right',
53
- // 'selector-closed',
54
- // 'selector-opened',
55
- // 'mode-dark',
56
- // 'mode-light'
57
- // ]
58
-
59
76
  export const defaultOptions = {
60
77
  id: 'id',
61
78
  label: 'label',
@@ -63,39 +80,6 @@ export const defaultOptions = {
63
80
  checked: 'checked'
64
81
  }
65
82
 
66
- /**
67
- * Structure to map custom fields for rendering
68
- *
69
- * @typedef FieldMapping
70
- * @property {string} [id='id'] - Unique id for the item
71
- * @property {string} [text='text'] - Attribute to identify the text to render
72
- * @property {string} [url='url'] - Attribute to identify a URL
73
- * @property {string} [icon='icon'] - Attribute to identify an icon class to render
74
- * @property {string} [image='image'] - Attribute to identify an image to render
75
- * @property {string} [children='children'] - Attribute to identify children of the current item
76
- * @property {string} [summary='summary']
77
- * @property {string} [notes='notes']
78
- * @property {string} [props='props']
79
- * @property {string} [isOpen='_open'] - Attribute to identify if the current item is open
80
- * @property {string} [isDeleted='_deleted'] - Attribute to identify if the current item is deleted
81
- * @property {FieldMapping} [fields] - Field mapping to be used on children in the next level
82
- */
83
- export const defaultFields = {
84
- id: 'id',
85
- url: 'url',
86
- text: 'text',
87
- children: 'data',
88
- icon: 'icon',
89
- image: 'image',
90
- component: 'component',
91
- summary: 'summary',
92
- notes: 'notes',
93
- props: 'props',
94
- target: 'target',
95
- isOpen: '_open',
96
- isDeleted: '_deleted'
97
- }
98
-
99
83
  export const defaultKeyMap = {
100
84
  ArrowRight: 'open',
101
85
  ArrowLeft: 'close',
@@ -105,6 +89,24 @@ export const defaultKeyMap = {
105
89
  Escape: 'deselect'
106
90
  }
107
91
 
92
+ export const defaultThemeMapping = {
93
+ neutral: 'slate',
94
+ primary: 'orange',
95
+ secondary: 'pink',
96
+ accent: 'sky',
97
+ success: 'green',
98
+ warning: 'yellow',
99
+ danger: 'red',
100
+ error: 'red',
101
+ info: 'cyan'
102
+ }
103
+
104
+ /**
105
+ * Generate a state icon mapping from a list of icon names
106
+ *
107
+ * @param {string[]} icons
108
+ * @returns {import('./types').StateIcons}
109
+ */
108
110
  export function stateIconsFromNames(icons) {
109
111
  return icons
110
112
  .map((k) => [...k.split('-')])
@@ -118,32 +120,3 @@ export function stateIconsFromNames(icons) {
118
120
  }
119
121
 
120
122
  export const defaultStateIcons = stateIconsFromNames(defaultIcons)
121
- // export const defaultStateIcons = {
122
- // accordion: {
123
- // opened: 'accordion-opened',
124
- // closed: 'accordion-closed'
125
- // },
126
- // item: {
127
- // remove: 'item-remove',
128
- // add: 'item-add',
129
- // clear: 'item-clear',
130
- // search: 'item-search'
131
- // },
132
- // node: {
133
- // opened: 'node-opened',
134
- // closed: 'node-closed'
135
- // },
136
- // list: {
137
- // selector: 'list-selector'
138
- // },
139
- // checkbox: {
140
- // checked: 'checkbox-checked',
141
- // unchecked: 'checkbox-unchecked',
142
- // unknown: 'checkbox-unknown'
143
- // },
144
- // rating: { filled: 'rating-filled', empty: 'rating-empty' },
145
- // radio: {
146
- // off: 'radio-off',
147
- // on: 'radio-on'
148
- // }
149
- // }
package/src/events.js ADDED
@@ -0,0 +1,32 @@
1
+ import { noop } from './utils.js'
2
+
3
+ /**
4
+ * Creates an emitter object from the given properties.
5
+ *
6
+ * - Filters attributes that start with 'on' and are functions,
7
+ * - Returns an object with keys that are the event names (without the 'on' prefix)
8
+ * - If a default event is not present in the props, it will be set to a no-op function.
9
+ *
10
+ * @param {Object} props - The properties object to filter.
11
+ * @param {Array<string>} defaults - An array of default events.
12
+ * @returns {import('./types.js').EventHandlers} The emitter object.
13
+ */
14
+ export function createEmitter(props, defaults = []) {
15
+ const emit = {}
16
+
17
+ // Filter and add functions that start with 'on'
18
+ Object.entries(props)
19
+ .filter(([key, value]) => key.startsWith('on') && typeof value === 'function')
20
+ .forEach(([key, value]) => {
21
+ emit[key.slice(2)] = value
22
+ })
23
+
24
+ // Add default events with no-op function if not present
25
+ defaults.forEach((event) => {
26
+ if (!emit[event]) {
27
+ emit[event] = noop
28
+ }
29
+ })
30
+
31
+ return emit
32
+ }
@@ -0,0 +1,148 @@
1
+ import { isNil, has, omit } from 'ramda'
2
+ import { defaultFields } from './constants.js'
3
+ import { isObject } from './utils.js'
4
+
5
+ export class FieldMapper {
6
+ #fields = { ...defaultFields }
7
+ #childMapper = null
8
+
9
+ constructor(fields = defaultFields) {
10
+ this.#updateFields(fields)
11
+ }
12
+
13
+ #updateFields(fields) {
14
+ Object.keys(fields).forEach((key) => {
15
+ this.#fields[key] = fields[key]
16
+ })
17
+ this.hasIcon = has(this.#fields.icon)
18
+ this.hasImage = has(this.#fields.image)
19
+ this.hasText = has(this.#fields.text)
20
+ this.hasValue = has(this.#fields.value)
21
+ this.hasLabel = has(this.#fields.label)
22
+ this.hasComponent = has(this.#fields.component)
23
+ this.hasCurrency = has(this.#fields.currency)
24
+ this.withPrefix = (x) => [this.#fields.iconPrefix, x].join('-').replace(/^-+/g, '')
25
+ this.excludeFlags = omit([
26
+ this.#fields.isDeleted,
27
+ this.#fields.isHidden,
28
+ this.#fields.isSelected,
29
+ this.#fields.isFiltered,
30
+ this.#fields.isOpen
31
+ ])
32
+ }
33
+
34
+ getChildMapper() {
35
+ if (!this.#childMapper) {
36
+ this.#childMapper = new FieldMapper(this.fields.fields ?? this.fields)
37
+ }
38
+ return this.#childMapper
39
+ }
40
+ /**
41
+ * @private
42
+ */
43
+ prop(fieldName, value) {
44
+ if (isNil(value)) return null
45
+
46
+ if (typeof value === 'object') {
47
+ return value[this.fields[fieldName]]
48
+ }
49
+
50
+ return fieldName === 'text' ? value : null
51
+ }
52
+
53
+ /**
54
+ * Gets a mapped attribute from the original item
55
+ *
56
+ * @param {string} fieldName - Name of the field to get
57
+ * @returns {any|null} - The attribute value or null if not found
58
+ */
59
+ get(fieldName, value, defaultValue = null) {
60
+ return this.prop(fieldName, value) ?? defaultValue
61
+ }
62
+
63
+ get fields() {
64
+ return this.#fields
65
+ }
66
+
67
+ set fields(fields) {
68
+ this.#updateFields(fields)
69
+ }
70
+
71
+ getIcon(value) {
72
+ if (!this.hasIcon(value)) return null
73
+ const icon = value[this.fields.icon]
74
+ if (isObject(icon)) return this.withPrefix(icon[value[this.fields.state]])
75
+ return this.withPrefix(icon)
76
+ }
77
+
78
+ getValue(value) {
79
+ if (this.hasValue(value)) {
80
+ return value[this.fields.value]
81
+ }
82
+ return value
83
+ }
84
+
85
+ getFormattedText(value, formatter) {
86
+ const text = this.get('text', value)
87
+
88
+ if (isNil(text)) return ''
89
+
90
+ if (typeof formatter !== 'function') return text.toString()
91
+
92
+ if (this.hasCurrency(value)) {
93
+ return formatter(text, this.get('currency', value))
94
+ }
95
+ return formatter(text)
96
+ }
97
+
98
+ hasChildren(item) {
99
+ return (
100
+ !isNil(item) &&
101
+ has(this.fields.children, item) &&
102
+ Array.isArray(item[this.fields.children]) &&
103
+ item[this.fields.children].length > 0
104
+ )
105
+ }
106
+
107
+ isNested(items) {
108
+ return Array.isArray(items) && items.some((item) => this.hasChildren(item))
109
+ }
110
+
111
+ getChildren(item) {
112
+ return this.hasChildren(item) ? item[this.fields.children] : []
113
+ }
114
+
115
+ /**
116
+ * Finds children by an index path
117
+ *
118
+ * @param {Array<Object>} items
119
+ * @param {Array<number>} path
120
+ * @returns {Array<Object>}
121
+ */
122
+ getChildrenByPath(items, path = []) {
123
+ const result = path.reduce(
124
+ (children, index) => children?.[index]?.[this.fields.children],
125
+ items
126
+ )
127
+
128
+ if (result === undefined) throw new Error('Invalid path')
129
+ return result
130
+ }
131
+
132
+ /**
133
+ * Finds an item by an index path
134
+ *
135
+ * @param {Array<Object>} items
136
+ * @param {Array<number>} path
137
+ * @returns {Object|null}
138
+ */
139
+ getItemByPath(items, path = []) {
140
+ const result = path.reduce(
141
+ (item, index, i) => (i === 0 ? items?.[index] : item?.[this.fields.children]?.[index]),
142
+ /* skipcq: JS-W1042 default undefined is needed */ undefined
143
+ )
144
+
145
+ if (result === undefined) throw new Error('Invalid path')
146
+ return result
147
+ }
148
+ }