@granularjs/ui 0.2.0 → 0.3.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.
- package/dist/granular-ui.min.js +208 -64
- package/dist/granular-ui.min.js.map +4 -4
- package/package.json +1 -1
- package/src/components/Autocomplete.js +179 -0
- package/src/components/DateInput.js +1 -3
- package/src/components/Pagination.js +2 -1
- package/src/components/ProgressRing.js +41 -7
- package/src/components/Radio.js +32 -3
- package/src/components/RadioGroup.js +24 -4
- package/src/components/RangePicker.js +66 -26
- package/src/components/Select.js +3 -1
- package/src/components/SelectSearch.js +2 -34
- package/src/components/Slider.js +15 -4
- package/src/components/Stepper.js +4 -3
- package/src/components/Switch.js +32 -4
- package/src/components/SwitchGroup.js +20 -4
- package/src/components/Table.js +39 -13
- package/src/components/Timeline.js +247 -10
- package/src/components/Toast.js +18 -6
- package/src/components/ToastStack.js +9 -15
- package/src/index.js +1 -0
- package/src/theme/icons.js +2 -1
- package/src/theme/styles.js +194 -50
- package/types/components/Autocomplete.d.ts +1 -0
- package/types/components/RadioGroup.d.ts +1 -0
- package/types/components/SwitchGroup.d.ts +1 -0
- package/types/index.d.ts +1 -0
- package/types/theme/icons.d.ts +1 -0
|
@@ -1,8 +1,24 @@
|
|
|
1
|
-
import { Div } from '@granularjs/core';
|
|
1
|
+
import { Div, context, state, after } from '@granularjs/core';
|
|
2
2
|
import { cx, splitPropsChildren } from '../utils.js';
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
export const switchGroupContext = context({ name: null, selected: null });
|
|
6
|
+
|
|
4
7
|
export function SwitchGroup(...args) {
|
|
5
|
-
const { props, children } = splitPropsChildren(args);
|
|
6
|
-
const { className, ...rest } = props;
|
|
7
|
-
|
|
8
|
+
const { props, rawProps, children } = splitPropsChildren(args);
|
|
9
|
+
const { className, name, selected, onChange: _onChange, ...rest } = props;
|
|
10
|
+
const { onChange } = rawProps;
|
|
11
|
+
|
|
12
|
+
const scope = switchGroupContext.scope({ name: name?.get(), selected: selected?.get() });
|
|
13
|
+
|
|
14
|
+
after(scope.selected).change((next) => {
|
|
15
|
+
onChange?.(next);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
after(selected).change((next) => {
|
|
19
|
+
if(next === scope.selected.get()) return;
|
|
20
|
+
scope.set().selected = next;
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
return scope.serve(Div({ ...rest, className: cx('g-ui-switch-group', className) }, children));
|
|
8
24
|
}
|
package/src/components/Table.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Table as HtmlTable, Thead, Tbody, Tr, Th, Td } from '@granularjs/core';
|
|
1
|
+
import { Table as HtmlTable, Thead, Tbody, Tr, Th, Td, list, when, after } from '@granularjs/core';
|
|
2
2
|
import { cx, splitPropsChildren, classFlag } from '../utils.js';
|
|
3
3
|
|
|
4
4
|
export function Table(...args) {
|
|
@@ -10,10 +10,13 @@ export function Table(...args) {
|
|
|
10
10
|
highlightOnHover,
|
|
11
11
|
withBorder,
|
|
12
12
|
withColumnBorders,
|
|
13
|
+
withRowBorders,
|
|
13
14
|
className,
|
|
14
15
|
style,
|
|
15
16
|
...rest
|
|
16
17
|
} = props;
|
|
18
|
+
|
|
19
|
+
const hasHeaders = after(headers).compute((next) => next.length > 0);
|
|
17
20
|
return HtmlTable(
|
|
18
21
|
{
|
|
19
22
|
...rest,
|
|
@@ -23,20 +26,43 @@ export function Table(...args) {
|
|
|
23
26
|
classFlag('g-ui-table-hover', highlightOnHover),
|
|
24
27
|
classFlag('g-ui-table-with-border', withBorder),
|
|
25
28
|
classFlag('g-ui-table-column-borders', withColumnBorders),
|
|
29
|
+
classFlag('g-ui-table-row-borders', withRowBorders),
|
|
26
30
|
className
|
|
27
31
|
),
|
|
28
32
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Tbody(
|
|
33
|
-
rows.map((row) =>
|
|
34
|
-
Tr(
|
|
35
|
-
Array.isArray(row)
|
|
36
|
-
? row.map((cell) => Td(cell))
|
|
37
|
-
: Object.values(row).map((cell) => Td(cell))
|
|
38
|
-
)
|
|
39
|
-
)
|
|
40
|
-
)
|
|
33
|
+
when(hasHeaders, () => Thead(
|
|
34
|
+
TableRow(headers, true)
|
|
35
|
+
)),
|
|
36
|
+
Tbody(list(rows, (row) => TableRow(row, false)))
|
|
41
37
|
);
|
|
42
38
|
}
|
|
39
|
+
const TableRow = (row, header) => {
|
|
40
|
+
const isArray = after(row).compute((next) => Array.isArray(next));
|
|
41
|
+
|
|
42
|
+
const ObjectRow = (row) => {
|
|
43
|
+
const cells = after(row).compute((next) => Object.values(next));
|
|
44
|
+
return ArrayRow(cells)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const ArrayRow = (row) => {
|
|
48
|
+
return list(row, (next) => {
|
|
49
|
+
console.log('INFO ABOUT NEXT', header);
|
|
50
|
+
return header ? TableHeaderCell(next) : TableCell(next)
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return Tr(
|
|
55
|
+
when(isArray,
|
|
56
|
+
() => ArrayRow(row),
|
|
57
|
+
() => ObjectRow(row)
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const TableCell = (content) => {
|
|
63
|
+
return Td(content)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const TableHeaderCell = (content) => {
|
|
67
|
+
return Th(content)
|
|
68
|
+
}
|
|
@@ -1,22 +1,259 @@
|
|
|
1
|
-
import { Div, when } from '@granularjs/core';
|
|
1
|
+
import { Div, when, list, after, resolve, state } from '@granularjs/core';
|
|
2
2
|
import { cx, splitPropsChildren } from '../utils.js';
|
|
3
3
|
|
|
4
|
+
const DOT_CENTER_OFFSET_PX = 10;
|
|
5
|
+
|
|
6
|
+
function getWeights(items) {
|
|
7
|
+
const list = items ?? [];
|
|
8
|
+
return list.map((item) => {
|
|
9
|
+
if (item == null) return 1;
|
|
10
|
+
const w = Number(item.weight);
|
|
11
|
+
return Number.isFinite(w) && w >= 0 ? w : 1;
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getWeightContext(items) {
|
|
16
|
+
const n = (items ?? []).length;
|
|
17
|
+
if (n < 2) return { totalWeight: 0, cumulativeWeights: [0] };
|
|
18
|
+
const weights = getWeights(items);
|
|
19
|
+
const segmentWeights = weights.slice(0, n - 1);
|
|
20
|
+
const totalWeight = segmentWeights.reduce((s, w) => s + w, 0);
|
|
21
|
+
const cumulativeWeights = [0];
|
|
22
|
+
for (let i = 0; i < segmentWeights.length; i++) {
|
|
23
|
+
cumulativeWeights.push(cumulativeWeights[i] + segmentWeights[i]);
|
|
24
|
+
}
|
|
25
|
+
return { totalWeight, cumulativeWeights };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function progressToActiveStepWeighted(progressPct, cumulativeWeights, totalWeight, n) {
|
|
29
|
+
if (n < 1 || totalWeight <= 0) return 0;
|
|
30
|
+
const pct = Math.max(0, Math.min(100, progressPct));
|
|
31
|
+
for (let k = n - 1; k >= 0; k--) {
|
|
32
|
+
const threshold = (cumulativeWeights[k] / totalWeight) * 100;
|
|
33
|
+
if (pct >= threshold) return k;
|
|
34
|
+
}
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function computeActiveStepAndFill(mode, active, progress, elapsedMs, stepDurationsMs, totalDurationMs, items) {
|
|
39
|
+
const m = mode;
|
|
40
|
+
const n = (items ?? []).length;
|
|
41
|
+
if (n === 0) return { activeStep: 0, progressPct: 0 };
|
|
42
|
+
|
|
43
|
+
if (m === 'step') {
|
|
44
|
+
const step = Math.max(0, Math.min(n - 1, Math.floor(active ?? 0)));
|
|
45
|
+
return { activeStep: step, progressPct: 0 };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (m === 'percent') {
|
|
49
|
+
const pct = Math.max(0, Math.min(100, Number(progress) || 0));
|
|
50
|
+
const ctx = getWeightContext(items);
|
|
51
|
+
const step = progressToActiveStepWeighted(pct, ctx.cumulativeWeights, ctx.totalWeight, n);
|
|
52
|
+
return { activeStep: step, progressPct: pct };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (m === 'time') {
|
|
56
|
+
const elapsed = Number(elapsedMs) || 0;
|
|
57
|
+
const durations = stepDurationsMs;
|
|
58
|
+
const total = totalDurationMs;
|
|
59
|
+
let totalDuration = 0;
|
|
60
|
+
if (Array.isArray(durations) && durations.length >= n) {
|
|
61
|
+
totalDuration = durations.slice(0, n).reduce((s, d) => s + (Number(d) || 0), 0);
|
|
62
|
+
} else if (typeof total === 'number' && total > 0) {
|
|
63
|
+
totalDuration = total;
|
|
64
|
+
}
|
|
65
|
+
if (totalDuration <= 0) return { activeStep: 0, progressPct: 0 };
|
|
66
|
+
const segment = totalDuration / n;
|
|
67
|
+
let step = 0;
|
|
68
|
+
if (Array.isArray(durations) && durations.length >= n) {
|
|
69
|
+
let cumulative = 0;
|
|
70
|
+
for (let i = 0; i < n; i++) {
|
|
71
|
+
cumulative += Number(durations[i]) || 0;
|
|
72
|
+
if (elapsed < cumulative) {
|
|
73
|
+
step = i;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
step = i;
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
step = Math.min(n - 1, Math.floor(elapsed / segment));
|
|
80
|
+
}
|
|
81
|
+
const progressPct = Math.min(100, (elapsed / totalDuration) * 100);
|
|
82
|
+
const ctx = getWeightContext(items);
|
|
83
|
+
const stepWeighted = progressToActiveStepWeighted(progressPct, ctx.cumulativeWeights, ctx.totalWeight, n);
|
|
84
|
+
return { activeStep: stepWeighted, progressPct };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return { activeStep: 0, progressPct: 0 };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function computeSegmentFillPercent(mode, activeStep, progressPct, segmentIndex, n, weightContext) {
|
|
91
|
+
if (n < 2 || segmentIndex < 0 || segmentIndex >= n - 1) return 0;
|
|
92
|
+
if (mode === 'step') {
|
|
93
|
+
return activeStep > segmentIndex ? 100 : 0;
|
|
94
|
+
}
|
|
95
|
+
const { totalWeight, cumulativeWeights } = weightContext ?? getWeightContext([]);
|
|
96
|
+
if (totalWeight <= 0) return 0;
|
|
97
|
+
const segmentStart = (cumulativeWeights[segmentIndex] / totalWeight) * 100;
|
|
98
|
+
const segmentEnd = (cumulativeWeights[segmentIndex + 1] / totalWeight) * 100;
|
|
99
|
+
if (progressPct <= segmentStart) return 0;
|
|
100
|
+
if (progressPct >= segmentEnd) return 100;
|
|
101
|
+
const range = segmentEnd - segmentStart;
|
|
102
|
+
return range <= 0 ? 0 : ((progressPct - segmentStart) / range) * 100;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let timelineIdCounter = 0;
|
|
106
|
+
|
|
107
|
+
function measureSegmentLayout(timelineId) {
|
|
108
|
+
const el = document.getElementById(timelineId);
|
|
109
|
+
if (!el) return;
|
|
110
|
+
const itemEls = el.querySelectorAll('.g-ui-timeline-item');
|
|
111
|
+
if (itemEls.length < 2) return [];
|
|
112
|
+
const segments = [];
|
|
113
|
+
for (let i = 0; i < itemEls.length - 1; i++) {
|
|
114
|
+
const top = itemEls[i].offsetTop + DOT_CENTER_OFFSET_PX;
|
|
115
|
+
const height = itemEls[i + 1].offsetTop - itemEls[i].offsetTop;
|
|
116
|
+
segments.push({ top, height });
|
|
117
|
+
}
|
|
118
|
+
return segments;
|
|
119
|
+
}
|
|
120
|
+
|
|
4
121
|
export function Timeline(...args) {
|
|
5
|
-
const { props } = splitPropsChildren(args, {
|
|
6
|
-
|
|
122
|
+
const { props, rawProps } = splitPropsChildren(args, {
|
|
123
|
+
items: [],
|
|
124
|
+
mode: 'step',
|
|
125
|
+
active: 0,
|
|
126
|
+
progress: 0,
|
|
127
|
+
elapsedMs: 0,
|
|
128
|
+
stepDurationsMs: null,
|
|
129
|
+
totalDurationMs: null,
|
|
130
|
+
clickable: false,
|
|
131
|
+
});
|
|
132
|
+
const {
|
|
133
|
+
items,
|
|
134
|
+
mode,
|
|
135
|
+
active,
|
|
136
|
+
progress,
|
|
137
|
+
elapsedMs,
|
|
138
|
+
stepDurationsMs,
|
|
139
|
+
totalDurationMs,
|
|
140
|
+
clickable,
|
|
141
|
+
className,
|
|
142
|
+
...rest
|
|
143
|
+
} = props;
|
|
144
|
+
const { onChange } = rawProps;
|
|
145
|
+
|
|
146
|
+
const timelineId = `g-ui-timeline-${++timelineIdCounter}`;
|
|
147
|
+
const segmentLayout = state([]);
|
|
148
|
+
|
|
149
|
+
const state_ = after(mode, active, progress, elapsedMs, stepDurationsMs, totalDurationMs, items).compute(
|
|
150
|
+
(values) => {
|
|
151
|
+
const [mode, active, progress, elapsedMs, stepDurationsMs, totalDurationMs, items] = values;
|
|
152
|
+
return computeActiveStepAndFill(
|
|
153
|
+
mode,
|
|
154
|
+
active,
|
|
155
|
+
progress,
|
|
156
|
+
elapsedMs,
|
|
157
|
+
stepDurationsMs,
|
|
158
|
+
totalDurationMs,
|
|
159
|
+
items
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const showTrack = after(mode).compute((m) => {
|
|
165
|
+
const v = resolve(m);
|
|
166
|
+
return v === 'time' || v === 'percent' || v === 'step';
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const resolvedMode = after(mode).compute((m) => resolve(m));
|
|
170
|
+
|
|
171
|
+
function scheduleMeasure() {
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
const segments = measureSegmentLayout(timelineId);
|
|
174
|
+
if (segments.length) segmentLayout.set(segments);
|
|
175
|
+
}, 0);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
after(items).change(() => scheduleMeasure());
|
|
179
|
+
scheduleMeasure();
|
|
180
|
+
|
|
7
181
|
return Div(
|
|
8
|
-
{
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
182
|
+
{
|
|
183
|
+
...rest,
|
|
184
|
+
id: timelineId,
|
|
185
|
+
className: cx(
|
|
186
|
+
'g-ui-timeline',
|
|
187
|
+
after(mode).compute((m) => (m ? `g-ui-timeline-mode-${resolve(m)}` : '')),
|
|
188
|
+
after(showTrack).compute((show) => (show ? 'g-ui-timeline-has-track' : '')),
|
|
189
|
+
after(clickable).compute((c) => (resolve(c) ? 'g-ui-timeline-clickable' : '')),
|
|
190
|
+
className
|
|
191
|
+
),
|
|
192
|
+
},
|
|
193
|
+
when(showTrack, () =>
|
|
194
|
+
list(segmentLayout, (seg, idx) => {
|
|
195
|
+
const segStyle = after(seg).compute((s) =>
|
|
196
|
+
s ? { top: `${s.top}px`, height: `${s.height}px` } : {}
|
|
197
|
+
);
|
|
198
|
+
const fillPct = after(state_, idx, items, resolvedMode).compute(([s, i, its, m]) => {
|
|
199
|
+
const itsList = its ?? [];
|
|
200
|
+
const n = itsList.length;
|
|
201
|
+
const weightContext = getWeightContext(itsList);
|
|
202
|
+
return computeSegmentFillPercent(
|
|
203
|
+
m,
|
|
204
|
+
s?.activeStep ?? 0,
|
|
205
|
+
s?.progressPct ?? 0,
|
|
206
|
+
resolve(i) ?? 0,
|
|
207
|
+
n,
|
|
208
|
+
weightContext
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
const fillHeight = after(fillPct).compute((p) => `${Math.max(0, Math.min(100, p))}%`);
|
|
212
|
+
return Div(
|
|
213
|
+
{
|
|
214
|
+
className: 'g-ui-timeline-track-segment',
|
|
215
|
+
style: after(segStyle).compute((x) => x),
|
|
216
|
+
},
|
|
217
|
+
Div({
|
|
218
|
+
className: 'g-ui-timeline-track-fill',
|
|
219
|
+
style: after(fillHeight).compute((h) => (h ? { height: h } : { height: '0%' })),
|
|
220
|
+
})
|
|
221
|
+
);
|
|
222
|
+
})
|
|
223
|
+
),
|
|
224
|
+
list(items, (item, idx) => {
|
|
225
|
+
const itemState = after(state_, idx).compute(([s, i]) => {
|
|
226
|
+
const step = s?.activeStep ?? 0;
|
|
227
|
+
const index = resolve(i) ?? 0;
|
|
228
|
+
if (index < step) return 'completed';
|
|
229
|
+
if (index === step) return 'active';
|
|
230
|
+
return 'future';
|
|
231
|
+
});
|
|
232
|
+
const itemClass = after(itemState).compute((st) => (st ? `g-ui-timeline-item-${st}` : ''));
|
|
233
|
+
const handleClick =
|
|
234
|
+
resolve(clickable) && typeof onChange === 'function'
|
|
235
|
+
? () => {
|
|
236
|
+
const i = resolve(idx);
|
|
237
|
+
if (typeof i === 'number') onChange(i);
|
|
238
|
+
}
|
|
239
|
+
: undefined;
|
|
240
|
+
return Div(
|
|
241
|
+
{
|
|
242
|
+
className: cx('g-ui-timeline-item', itemClass),
|
|
243
|
+
onClick: handleClick,
|
|
244
|
+
role: handleClick ? 'button' : undefined,
|
|
245
|
+
tabIndex: handleClick ? 0 : undefined,
|
|
246
|
+
},
|
|
12
247
|
Div({ className: 'g-ui-timeline-dot' }),
|
|
13
248
|
Div(
|
|
14
249
|
{ className: 'g-ui-timeline-content' },
|
|
15
250
|
when(item.title, () => Div({ className: 'g-ui-timeline-title' }, item.title)),
|
|
16
|
-
when(item.description, () =>
|
|
251
|
+
when(item.description, () =>
|
|
252
|
+
Div({ className: 'g-ui-timeline-desc' }, item.description)
|
|
253
|
+
),
|
|
17
254
|
item.content
|
|
18
255
|
)
|
|
19
|
-
)
|
|
20
|
-
)
|
|
256
|
+
);
|
|
257
|
+
})
|
|
21
258
|
);
|
|
22
259
|
}
|
package/src/components/Toast.js
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
import { Div, Button, when } from '@granularjs/core';
|
|
1
|
+
import { Div, Button, when, state} from '@granularjs/core';
|
|
2
2
|
import { cx, splitPropsChildren } from '../utils.js';
|
|
3
|
+
import { closeSvg } from '../theme/icons.js';
|
|
4
|
+
import { Icon } from './Icon.js';
|
|
3
5
|
|
|
4
6
|
export function Toast(...args) {
|
|
5
|
-
const { props, children } = splitPropsChildren(args);
|
|
6
|
-
const { title,
|
|
7
|
-
|
|
7
|
+
const { props, rawProps, children } = splitPropsChildren(args);
|
|
8
|
+
const { title, className, ...rest } = props;
|
|
9
|
+
const { onClose } = rawProps;
|
|
10
|
+
const visible = state(true);
|
|
11
|
+
const close = () => {
|
|
12
|
+
visible.set(false);
|
|
13
|
+
onClose?.();
|
|
14
|
+
console.log('close');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return when(visible, () => Div(
|
|
8
18
|
{ ...rest, className: cx('g-ui-toast', className) },
|
|
9
19
|
Div(
|
|
10
20
|
{ className: 'g-ui-toast-row' },
|
|
11
21
|
when(title, () => Div({ className: 'g-ui-toast-title' }, title)),
|
|
12
|
-
|
|
22
|
+
Button({ className: 'g-ui-toast-close', onClick: close },
|
|
23
|
+
Icon({ innerHTML: closeSvg })
|
|
24
|
+
)
|
|
13
25
|
),
|
|
14
26
|
children
|
|
15
|
-
)
|
|
27
|
+
))
|
|
16
28
|
}
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
import { Div, when } from '@granularjs/core';
|
|
1
|
+
import { Div, when, list, portal } from '@granularjs/core';
|
|
2
2
|
import { cx, splitPropsChildren } from '../utils.js';
|
|
3
|
+
import { Toast } from './Toast.js';
|
|
3
4
|
|
|
4
5
|
export function ToastStack(...args) {
|
|
5
|
-
const { props } = splitPropsChildren(args, { items: [] });
|
|
6
|
-
const { items, className,
|
|
7
|
-
|
|
6
|
+
const { props, rawProps } = splitPropsChildren(args, { items: [] });
|
|
7
|
+
const { items, className, timeout, ...rest } = props;
|
|
8
|
+
const { onClose } = rawProps;
|
|
9
|
+
return portal(Div(
|
|
8
10
|
{ ...rest, className: cx('g-ui-toast-stack', className) },
|
|
9
|
-
items
|
|
10
|
-
|
|
11
|
-
{ className: cx('g-ui-toast', [timeout, 'g-ui-toast-auto']) },
|
|
12
|
-
Div(
|
|
13
|
-
{ className: 'g-ui-toast-row' },
|
|
14
|
-
when(item.title, () => Div({ className: 'g-ui-toast-title' }, item.title)),
|
|
15
|
-
when(onClose, () => Div({ className: 'g-ui-toast-close', onClick: () => onClose(item) }, '×'))
|
|
16
|
-
),
|
|
17
|
-
item.message
|
|
18
|
-
)
|
|
11
|
+
list(items, (item) =>
|
|
12
|
+
Toast({ title: item.title, onClose: () => onClose?.(item) }, item.message)
|
|
19
13
|
)
|
|
20
|
-
);
|
|
14
|
+
));
|
|
21
15
|
}
|
package/src/index.js
CHANGED
|
@@ -76,6 +76,7 @@ export { SearchInput } from './components/SearchInput.js';
|
|
|
76
76
|
export { CopyButton } from './components/CopyButton.js';
|
|
77
77
|
export { ProgressRing } from './components/ProgressRing.js';
|
|
78
78
|
export { Toast } from './components/Toast.js';
|
|
79
|
+
export { Autocomplete } from './components/Autocomplete.js';
|
|
79
80
|
export { SelectSearch } from './components/SelectSearch.js';
|
|
80
81
|
export { SwitchGroup } from './components/SwitchGroup.js';
|
|
81
82
|
export { RangePicker } from './components/RangePicker.js';
|
package/src/theme/icons.js
CHANGED
|
@@ -7,4 +7,5 @@ export const searchSvg = '<svg xmlns="http://www.w3.org/2000/svg" height="24px"
|
|
|
7
7
|
export const plusSvg = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z"/></svg>';
|
|
8
8
|
export const editSvg = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h357l-80 80H200v560h560v-278l80-80v358q0 33-23.5 56.5T760-120H200Zm280-360v-80h240v80H480Zm0 160v-80h320v80H480Zm0 160v-80h320v80H480ZM360-360v-80h80v80h-80Zm0 160v-80h80v80h-80Zm0 160v-80h80v80h-80Zm160-320h280l-36-37 37-37v74H520Zm-160 0h80v-80h-80v80ZM120-600v-160l160-160h160l-80 80H200v240h-80Zm80-240v-80 80Z"/></svg>';
|
|
9
9
|
export const deleteSvg = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/></svg>';
|
|
10
|
-
export const calendarTodaySvg = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Z"/></svg>';
|
|
10
|
+
export const calendarTodaySvg = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Z"/></svg>';
|
|
11
|
+
export const keyboardArrowDownSvg = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#1f1f1f"><path d="M480-344 240-584l56-56 184 184 184-184 56 56-240 240Z"/></svg>';
|