@cratis/scene.blueprint.default 4.38.0 → 4.40.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/ComponentName.ts +27 -0
- package/defaultBlueprintComponents.ts +10 -1
- package/dist/cjs/ComponentName.js +9 -0
- package/dist/cjs/ComponentName.js.map +1 -1
- package/dist/cjs/defaultBlueprintComponents.js +19 -1
- package/dist/cjs/defaultBlueprintComponents.js.map +1 -1
- package/dist/cjs/foundation/BulkBar.js +62 -0
- package/dist/cjs/foundation/BulkBar.js.map +1 -0
- package/dist/cjs/foundation/DataList.js +436 -0
- package/dist/cjs/foundation/DataList.js.map +1 -0
- package/dist/cjs/foundation/FormScreenBody.js +447 -0
- package/dist/cjs/foundation/FormScreenBody.js.map +1 -0
- package/dist/cjs/foundation/FoundationStates.js +2 -1
- package/dist/cjs/foundation/FoundationStates.js.map +1 -1
- package/dist/cjs/foundation/GlobalSearch.js +54 -0
- package/dist/cjs/foundation/GlobalSearch.js.map +1 -0
- package/dist/cjs/foundation/KanbanBoard.js +222 -0
- package/dist/cjs/foundation/KanbanBoard.js.map +1 -0
- package/dist/cjs/foundation/NotificationsButton.js +45 -0
- package/dist/cjs/foundation/NotificationsButton.js.map +1 -0
- package/dist/cjs/foundation/SubNavigation.js +72 -0
- package/dist/cjs/foundation/SubNavigation.js.map +1 -0
- package/dist/cjs/foundation/TabSet.js +101 -0
- package/dist/cjs/foundation/TabSet.js.map +1 -0
- package/dist/cjs/foundation/WizardProgress.js +185 -0
- package/dist/cjs/foundation/WizardProgress.js.map +1 -0
- package/dist/cjs/foundation/boardModel.js +67 -0
- package/dist/cjs/foundation/boardModel.js.map +1 -0
- package/dist/cjs/foundation/formModel.js +158 -0
- package/dist/cjs/foundation/formModel.js.map +1 -0
- package/dist/cjs/foundation/foundationComponentMetadata.js +54 -0
- package/dist/cjs/foundation/foundationComponentMetadata.js.map +1 -1
- package/dist/cjs/foundation/foundationDescriptors.js +400 -0
- package/dist/cjs/foundation/foundationDescriptors.js.map +1 -1
- package/dist/cjs/foundation/foundationSamples.js +303 -0
- package/dist/cjs/foundation/foundationSamples.js.map +1 -1
- package/dist/cjs/foundation/foundationStrings.js +72 -0
- package/dist/cjs/foundation/foundationStrings.js.map +1 -1
- package/dist/cjs/foundation/listModel.js +200 -0
- package/dist/cjs/foundation/listModel.js.map +1 -0
- package/dist/cjs/foundation/tabModel.js +41 -0
- package/dist/cjs/foundation/tabModel.js.map +1 -0
- package/dist/cjs/foundation/urlState.js +57 -0
- package/dist/cjs/foundation/urlState.js.map +1 -0
- package/dist/cjs/foundation/useCompactWidth.js +23 -0
- package/dist/cjs/foundation/useCompactWidth.js.map +1 -0
- package/dist/cjs/foundation/wizardModel.js +50 -0
- package/dist/cjs/foundation/wizardModel.js.map +1 -0
- package/dist/cjs/index.js +71 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/ComponentName.d.ts +10 -1
- package/dist/esm/ComponentName.d.ts.map +1 -1
- package/dist/esm/ComponentName.js +9 -0
- package/dist/esm/ComponentName.js.map +1 -1
- package/dist/esm/defaultBlueprintComponents.d.ts.map +1 -1
- package/dist/esm/defaultBlueprintComponents.js +19 -1
- package/dist/esm/defaultBlueprintComponents.js.map +1 -1
- package/dist/esm/foundation/BulkBar.d.ts +4 -0
- package/dist/esm/foundation/BulkBar.d.ts.map +1 -0
- package/dist/esm/foundation/BulkBar.js +59 -0
- package/dist/esm/foundation/BulkBar.js.map +1 -0
- package/dist/esm/foundation/DataList.d.ts +3 -0
- package/dist/esm/foundation/DataList.d.ts.map +1 -0
- package/dist/esm/foundation/DataList.js +434 -0
- package/dist/esm/foundation/DataList.js.map +1 -0
- package/dist/esm/foundation/FormScreenBody.d.ts +3 -0
- package/dist/esm/foundation/FormScreenBody.d.ts.map +1 -0
- package/dist/esm/foundation/FormScreenBody.js +445 -0
- package/dist/esm/foundation/FormScreenBody.js.map +1 -0
- package/dist/esm/foundation/FoundationStates.js +2 -1
- package/dist/esm/foundation/FoundationStates.js.map +1 -1
- package/dist/esm/foundation/GlobalSearch.d.ts +3 -0
- package/dist/esm/foundation/GlobalSearch.d.ts.map +1 -0
- package/dist/esm/foundation/GlobalSearch.js +52 -0
- package/dist/esm/foundation/GlobalSearch.js.map +1 -0
- package/dist/esm/foundation/KanbanBoard.d.ts +3 -0
- package/dist/esm/foundation/KanbanBoard.d.ts.map +1 -0
- package/dist/esm/foundation/KanbanBoard.js +220 -0
- package/dist/esm/foundation/KanbanBoard.js.map +1 -0
- package/dist/esm/foundation/NotificationsButton.d.ts +3 -0
- package/dist/esm/foundation/NotificationsButton.d.ts.map +1 -0
- package/dist/esm/foundation/NotificationsButton.js +43 -0
- package/dist/esm/foundation/NotificationsButton.js.map +1 -0
- package/dist/esm/foundation/SubNavigation.d.ts +3 -0
- package/dist/esm/foundation/SubNavigation.d.ts.map +1 -0
- package/dist/esm/foundation/SubNavigation.js +70 -0
- package/dist/esm/foundation/SubNavigation.js.map +1 -0
- package/dist/esm/foundation/TabSet.d.ts +3 -0
- package/dist/esm/foundation/TabSet.d.ts.map +1 -0
- package/dist/esm/foundation/TabSet.js +99 -0
- package/dist/esm/foundation/TabSet.js.map +1 -0
- package/dist/esm/foundation/WizardProgress.d.ts +3 -0
- package/dist/esm/foundation/WizardProgress.d.ts.map +1 -0
- package/dist/esm/foundation/WizardProgress.js +183 -0
- package/dist/esm/foundation/WizardProgress.js.map +1 -0
- package/dist/esm/foundation/boardModel.d.ts +22 -0
- package/dist/esm/foundation/boardModel.d.ts.map +1 -0
- package/dist/esm/foundation/boardModel.js +61 -0
- package/dist/esm/foundation/boardModel.js.map +1 -0
- package/dist/esm/foundation/formModel.d.ts +48 -0
- package/dist/esm/foundation/formModel.d.ts.map +1 -0
- package/dist/esm/foundation/formModel.js +147 -0
- package/dist/esm/foundation/formModel.js.map +1 -0
- package/dist/esm/foundation/foundationComponentMetadata.d.ts.map +1 -1
- package/dist/esm/foundation/foundationComponentMetadata.js +54 -0
- package/dist/esm/foundation/foundationComponentMetadata.js.map +1 -1
- package/dist/esm/foundation/foundationDescriptors.d.ts.map +1 -1
- package/dist/esm/foundation/foundationDescriptors.js +400 -0
- package/dist/esm/foundation/foundationDescriptors.js.map +1 -1
- package/dist/esm/foundation/foundationSamples.d.ts.map +1 -1
- package/dist/esm/foundation/foundationSamples.js +303 -0
- package/dist/esm/foundation/foundationSamples.js.map +1 -1
- package/dist/esm/foundation/foundationStrings.d.ts +72 -0
- package/dist/esm/foundation/foundationStrings.d.ts.map +1 -1
- package/dist/esm/foundation/foundationStrings.js +72 -0
- package/dist/esm/foundation/foundationStrings.js.map +1 -1
- package/dist/esm/foundation/index.d.ts +16 -0
- package/dist/esm/foundation/index.d.ts.map +1 -1
- package/dist/esm/foundation/index.js +16 -0
- package/dist/esm/foundation/index.js.map +1 -1
- package/dist/esm/foundation/listModel.d.ts +49 -0
- package/dist/esm/foundation/listModel.d.ts.map +1 -0
- package/dist/esm/foundation/listModel.js +183 -0
- package/dist/esm/foundation/listModel.js.map +1 -0
- package/dist/esm/foundation/tabModel.d.ts +10 -0
- package/dist/esm/foundation/tabModel.d.ts.map +1 -0
- package/dist/esm/foundation/tabModel.js +37 -0
- package/dist/esm/foundation/tabModel.js.map +1 -0
- package/dist/esm/foundation/urlState.d.ts +4 -0
- package/dist/esm/foundation/urlState.d.ts.map +1 -0
- package/dist/esm/foundation/urlState.js +53 -0
- package/dist/esm/foundation/urlState.js.map +1 -0
- package/dist/esm/foundation/useCompactWidth.d.ts +3 -0
- package/dist/esm/foundation/useCompactWidth.d.ts.map +1 -0
- package/dist/esm/foundation/useCompactWidth.js +20 -0
- package/dist/esm/foundation/useCompactWidth.js.map +1 -0
- package/dist/esm/foundation/wizardModel.d.ts +16 -0
- package/dist/esm/foundation/wizardModel.d.ts.map +1 -0
- package/dist/esm/foundation/wizardModel.js +43 -0
- package/dist/esm/foundation/wizardModel.js.map +1 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/foundation/BulkBar.tsx +38 -0
- package/foundation/DataList.tsx +208 -0
- package/foundation/FormScreenBody.tsx +196 -0
- package/foundation/FoundationStates.tsx +1 -1
- package/foundation/GlobalSearch.tsx +33 -0
- package/foundation/KanbanBoard.tsx +97 -0
- package/foundation/NotificationsButton.tsx +28 -0
- package/foundation/SubNavigation.tsx +49 -0
- package/foundation/TabSet.tsx +65 -0
- package/foundation/WizardProgress.tsx +109 -0
- package/foundation/boardModel.ts +64 -0
- package/foundation/formModel.ts +146 -0
- package/foundation/foundationComponentMetadata.ts +9 -0
- package/foundation/foundationDescriptors.ts +195 -0
- package/foundation/foundationSamples.ts +56 -0
- package/foundation/foundationStrings.ts +72 -0
- package/foundation/index.ts +16 -0
- package/foundation/listModel.ts +190 -0
- package/foundation/tabModel.ts +41 -0
- package/foundation/urlState.ts +52 -0
- package/foundation/useCompactWidth.ts +23 -0
- package/foundation/wizardModel.ts +54 -0
- package/package.json +8 -8
- package/shell/layout.css +513 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useMemo, useState, useEffect } from 'react';
|
|
3
|
+
import { useValueOutput } from '@cratis/scene.react';
|
|
4
|
+
import { readColumnsOfBoard, readCards, cardsOf, overLimit, moveCard } from './boardModel.js';
|
|
5
|
+
import { readComponentState, ComponentState } from './ComponentState.js';
|
|
6
|
+
import { FoundationIcon } from './FoundationIcon.js';
|
|
7
|
+
import { readFoundationStrings, formatText } from './foundationStrings.js';
|
|
8
|
+
import { readPermissionRule } from './PermissionRule.js';
|
|
9
|
+
import { FoundationFrame } from './StateFrame.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The `kanbanBoard` component: columns mapped to a status or stage, with cards that move between them.
|
|
13
|
+
*
|
|
14
|
+
* `columns` (`id`, `label`, `limit`) and `cards` (`id`, `title`, `column`, `assignee`, up to three `fields`, `badges`) come from a query. A card moves by
|
|
15
|
+
* dragging it to another column **and** by its own "Move to" menu - the keyboard and screen-reader alternative, so nothing depends on a pointer
|
|
16
|
+
* - and every move is announced. Columns show their count and a limit indicator that says "Over the limit" in words, and collapse to a
|
|
17
|
+
* strip. The new arrangement is published as `value` (the cards with their columns) for the screen to save; with `editPermission` not enabled the
|
|
18
|
+
* board is read-only. A card whose column no longer exists is shown in the first column rather than lost.
|
|
19
|
+
*/ function KanbanBoard({ element, interactions, bindingOutputs }) {
|
|
20
|
+
const columns = useMemo(()=>readColumnsOfBoard(element.properties.columns), [
|
|
21
|
+
element.properties.columns
|
|
22
|
+
]);
|
|
23
|
+
const supplied = useMemo(()=>readCards(element.properties.cards), [
|
|
24
|
+
element.properties.cards
|
|
25
|
+
]);
|
|
26
|
+
const suppliedKey = JSON.stringify(supplied);
|
|
27
|
+
const [cards, setCards] = useState(supplied);
|
|
28
|
+
const [collapsed, setCollapsed] = useState(new Set());
|
|
29
|
+
const [announcement, setAnnouncement] = useState('');
|
|
30
|
+
const [dragging, setDragging] = useState();
|
|
31
|
+
const strings = readFoundationStrings(element);
|
|
32
|
+
const state = readComponentState(element, columns.length > 0);
|
|
33
|
+
const locked = readPermissionRule(element, 'editPermission') !== 'enabled';
|
|
34
|
+
useEffect(()=>setCards(supplied), [
|
|
35
|
+
suppliedKey
|
|
36
|
+
]);
|
|
37
|
+
useValueOutput(bindingOutputs, cards.map((card)=>({
|
|
38
|
+
id: card.id,
|
|
39
|
+
column: card.column
|
|
40
|
+
})));
|
|
41
|
+
const move = (id, to)=>{
|
|
42
|
+
const card = cards.find((candidate)=>candidate.id === id);
|
|
43
|
+
const target = columns.find((column)=>column.id === to);
|
|
44
|
+
const next = moveCard(columns, cards, id, to);
|
|
45
|
+
if (!card || !target || next === cards) return;
|
|
46
|
+
setCards(next);
|
|
47
|
+
setAnnouncement(formatText(strings.boardMoved, {
|
|
48
|
+
title: card.title,
|
|
49
|
+
column: target.label
|
|
50
|
+
}));
|
|
51
|
+
interactions?.onChange?.();
|
|
52
|
+
};
|
|
53
|
+
const drop = (event, to)=>{
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
if (dragging) move(dragging, to);
|
|
56
|
+
setDragging(undefined);
|
|
57
|
+
};
|
|
58
|
+
const toggle = (id)=>setCollapsed((current)=>{
|
|
59
|
+
const next = new Set(current);
|
|
60
|
+
if (next.has(id)) next.delete(id);
|
|
61
|
+
else next.add(id);
|
|
62
|
+
return next;
|
|
63
|
+
});
|
|
64
|
+
return /*#__PURE__*/ jsx(FoundationFrame, {
|
|
65
|
+
element: element,
|
|
66
|
+
interactions: interactions,
|
|
67
|
+
name: "kanban-board",
|
|
68
|
+
state: state,
|
|
69
|
+
skeleton: [
|
|
70
|
+
100,
|
|
71
|
+
100,
|
|
72
|
+
100
|
|
73
|
+
],
|
|
74
|
+
children: (state === ComponentState.Ready || state === ComponentState.Partial) && /*#__PURE__*/ jsxs(Fragment, {
|
|
75
|
+
children: [
|
|
76
|
+
/*#__PURE__*/ jsx("div", {
|
|
77
|
+
role: "status",
|
|
78
|
+
"aria-live": "polite",
|
|
79
|
+
className: "foundation-visually-hidden",
|
|
80
|
+
children: announcement
|
|
81
|
+
}),
|
|
82
|
+
/*#__PURE__*/ jsx("div", {
|
|
83
|
+
className: "foundation-board",
|
|
84
|
+
children: columns.map((column)=>{
|
|
85
|
+
const inColumn = cardsOf(columns, cards, column.id);
|
|
86
|
+
const closed = collapsed.has(column.id);
|
|
87
|
+
const over = overLimit(column, inColumn.length);
|
|
88
|
+
return /*#__PURE__*/ jsxs("section", {
|
|
89
|
+
className: "foundation-board-column",
|
|
90
|
+
"data-collapsed": closed,
|
|
91
|
+
"data-over": over,
|
|
92
|
+
"aria-label": formatText(strings.boardColumn, {
|
|
93
|
+
column: column.label,
|
|
94
|
+
count: inColumn.length
|
|
95
|
+
}),
|
|
96
|
+
onDragOver: (event)=>{
|
|
97
|
+
if (!locked) event.preventDefault();
|
|
98
|
+
},
|
|
99
|
+
onDrop: (event)=>{
|
|
100
|
+
if (!locked) drop(event, column.id);
|
|
101
|
+
},
|
|
102
|
+
children: [
|
|
103
|
+
/*#__PURE__*/ jsxs("header", {
|
|
104
|
+
className: "foundation-board-header",
|
|
105
|
+
children: [
|
|
106
|
+
/*#__PURE__*/ jsx("button", {
|
|
107
|
+
type: "button",
|
|
108
|
+
className: "foundation-icon-button",
|
|
109
|
+
"aria-expanded": !closed,
|
|
110
|
+
"aria-label": formatText(closed ? strings.boardExpand : strings.boardCollapse, {
|
|
111
|
+
column: column.label
|
|
112
|
+
}),
|
|
113
|
+
onClick: ()=>toggle(column.id),
|
|
114
|
+
children: /*#__PURE__*/ jsx(FoundationIcon, {
|
|
115
|
+
name: closed ? 'chevron-right' : 'chevron-down'
|
|
116
|
+
})
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ jsx("h3", {
|
|
119
|
+
children: column.label
|
|
120
|
+
}),
|
|
121
|
+
/*#__PURE__*/ jsxs("span", {
|
|
122
|
+
className: "foundation-count",
|
|
123
|
+
children: [
|
|
124
|
+
inColumn.length,
|
|
125
|
+
column.limit > 0 ? ` / ${column.limit}` : ''
|
|
126
|
+
]
|
|
127
|
+
}),
|
|
128
|
+
over && /*#__PURE__*/ jsxs("span", {
|
|
129
|
+
className: "foundation-chip",
|
|
130
|
+
"data-tone": "danger",
|
|
131
|
+
children: [
|
|
132
|
+
/*#__PURE__*/ jsx(FoundationIcon, {
|
|
133
|
+
name: "alert"
|
|
134
|
+
}),
|
|
135
|
+
formatText(strings.boardWipExceeded, {
|
|
136
|
+
limit: column.limit
|
|
137
|
+
})
|
|
138
|
+
]
|
|
139
|
+
})
|
|
140
|
+
]
|
|
141
|
+
}),
|
|
142
|
+
!closed && /*#__PURE__*/ jsxs("ul", {
|
|
143
|
+
className: "foundation-board-cards",
|
|
144
|
+
children: [
|
|
145
|
+
inColumn.length === 0 && /*#__PURE__*/ jsx("li", {
|
|
146
|
+
className: "foundation-count",
|
|
147
|
+
children: strings.boardNoCards
|
|
148
|
+
}),
|
|
149
|
+
inColumn.map((card)=>/*#__PURE__*/ jsxs("li", {
|
|
150
|
+
className: "foundation-board-card",
|
|
151
|
+
draggable: !locked,
|
|
152
|
+
onDragStart: ()=>setDragging(card.id),
|
|
153
|
+
onDragEnd: ()=>setDragging(undefined),
|
|
154
|
+
children: [
|
|
155
|
+
/*#__PURE__*/ jsx("strong", {
|
|
156
|
+
children: card.title
|
|
157
|
+
}),
|
|
158
|
+
card.assignee && /*#__PURE__*/ jsxs("span", {
|
|
159
|
+
className: "foundation-count",
|
|
160
|
+
children: [
|
|
161
|
+
/*#__PURE__*/ jsx(FoundationIcon, {
|
|
162
|
+
name: "user"
|
|
163
|
+
}),
|
|
164
|
+
" ",
|
|
165
|
+
card.assignee
|
|
166
|
+
]
|
|
167
|
+
}),
|
|
168
|
+
card.fields.map((field)=>/*#__PURE__*/ jsxs("span", {
|
|
169
|
+
className: "foundation-board-field",
|
|
170
|
+
children: [
|
|
171
|
+
/*#__PURE__*/ jsx("span", {
|
|
172
|
+
className: "foundation-count",
|
|
173
|
+
children: field.label
|
|
174
|
+
}),
|
|
175
|
+
" ",
|
|
176
|
+
field.value
|
|
177
|
+
]
|
|
178
|
+
}, field.label)),
|
|
179
|
+
card.badges.length > 0 && /*#__PURE__*/ jsx("span", {
|
|
180
|
+
className: "foundation-board-badges",
|
|
181
|
+
children: card.badges.map((badge)=>/*#__PURE__*/ jsx("span", {
|
|
182
|
+
className: "foundation-chip",
|
|
183
|
+
"data-tone": "neutral",
|
|
184
|
+
children: badge
|
|
185
|
+
}, badge))
|
|
186
|
+
}),
|
|
187
|
+
!locked && /*#__PURE__*/ jsxs("select", {
|
|
188
|
+
className: "foundation-board-move",
|
|
189
|
+
"aria-label": formatText(strings.boardMoveCard, {
|
|
190
|
+
title: card.title
|
|
191
|
+
}),
|
|
192
|
+
value: column.id,
|
|
193
|
+
onChange: (event)=>move(card.id, event.target.value),
|
|
194
|
+
children: [
|
|
195
|
+
/*#__PURE__*/ jsx("option", {
|
|
196
|
+
value: column.id,
|
|
197
|
+
disabled: true,
|
|
198
|
+
children: strings.boardMoveTo
|
|
199
|
+
}),
|
|
200
|
+
columns.filter((other)=>other.id !== column.id).map((other)=>/*#__PURE__*/ jsx("option", {
|
|
201
|
+
value: other.id,
|
|
202
|
+
children: other.label
|
|
203
|
+
}, other.id))
|
|
204
|
+
]
|
|
205
|
+
})
|
|
206
|
+
]
|
|
207
|
+
}, card.id))
|
|
208
|
+
]
|
|
209
|
+
})
|
|
210
|
+
]
|
|
211
|
+
}, column.id);
|
|
212
|
+
})
|
|
213
|
+
})
|
|
214
|
+
]
|
|
215
|
+
})
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export { KanbanBoard };
|
|
220
|
+
//# sourceMappingURL=KanbanBoard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KanbanBoard.js","sources":["../../../foundation/KanbanBoard.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DragEvent, useEffect, useMemo, useState } from 'react';\nimport { RegisteredComponentProps, useValueOutput } from '@cratis/scene.react';\nimport { BoardCard, BoardColumn, cardsOf, moveCard, overLimit, readCards, readColumnsOfBoard } from './boardModel';\nimport { ComponentState, readComponentState } from './ComponentState';\nimport { FoundationIcon } from './FoundationIcon';\nimport { formatText, readFoundationStrings } from './foundationStrings';\nimport { readPermissionRule } from './PermissionRule';\nimport { FoundationFrame } from './StateFrame';\n\n/**\n * The `kanbanBoard` component: columns mapped to a status or stage, with cards that move between them.\n *\n * `columns` (`id`, `label`, `limit`) and `cards` (`id`, `title`, `column`, `assignee`, up to three `fields`, `badges`) come from a query. A card moves by\n * dragging it to another column **and** by its own \"Move to\" menu - the keyboard and screen-reader alternative, so nothing depends on a pointer\n * - and every move is announced. Columns show their count and a limit indicator that says \"Over the limit\" in words, and collapse to a\n * strip. The new arrangement is published as `value` (the cards with their columns) for the screen to save; with `editPermission` not enabled the\n * board is read-only. A card whose column no longer exists is shown in the first column rather than lost.\n */\nexport function KanbanBoard({ element, interactions, bindingOutputs }: RegisteredComponentProps) {\n const columns = useMemo(() => readColumnsOfBoard(element.properties.columns), [element.properties.columns]);\n const supplied = useMemo(() => readCards(element.properties.cards), [element.properties.cards]);\n const suppliedKey = JSON.stringify(supplied);\n const [cards, setCards] = useState<BoardCard[]>(supplied);\n const [collapsed, setCollapsed] = useState<Set<string>>(new Set());\n const [announcement, setAnnouncement] = useState('');\n const [dragging, setDragging] = useState<string | undefined>();\n const strings = readFoundationStrings(element);\n const state = readComponentState(element, columns.length > 0);\n const locked = readPermissionRule(element, 'editPermission') !== 'enabled';\n\n useEffect(() => setCards(supplied), [suppliedKey]);\n useValueOutput(bindingOutputs, cards.map(card => ({ id: card.id, column: card.column })));\n\n const move = (id: string, to: string) => {\n const card = cards.find(candidate => candidate.id === id);\n const target = columns.find(column => column.id === to);\n const next = moveCard(columns, cards, id, to);\n if (!card || !target || next === cards) return;\n setCards(next);\n setAnnouncement(formatText(strings.boardMoved, { title: card.title, column: target.label }));\n interactions?.onChange?.();\n };\n const drop = (event: DragEvent, to: string) => { event.preventDefault(); if (dragging) move(dragging, to); setDragging(undefined); };\n const toggle = (id: string) => setCollapsed(current => { const next = new Set(current); if (next.has(id)) next.delete(id); else next.add(id); return next; });\n\n return (\n <FoundationFrame element={element} interactions={interactions} name='kanban-board' state={state} skeleton={[100, 100, 100]}>\n {(state === ComponentState.Ready || state === ComponentState.Partial) && (\n <>\n <div role='status' aria-live='polite' className='foundation-visually-hidden'>{announcement}</div>\n <div className='foundation-board'>\n {columns.map((column: BoardColumn) => {\n const inColumn = cardsOf(columns, cards, column.id);\n const closed = collapsed.has(column.id);\n const over = overLimit(column, inColumn.length);\n return (\n <section key={column.id} className='foundation-board-column' data-collapsed={closed} data-over={over} aria-label={formatText(strings.boardColumn, { column: column.label, count: inColumn.length })}\n onDragOver={event => { if (!locked) event.preventDefault(); }} onDrop={event => { if (!locked) drop(event, column.id); }}>\n <header className='foundation-board-header'>\n <button type='button' className='foundation-icon-button' aria-expanded={!closed} aria-label={formatText(closed ? strings.boardExpand : strings.boardCollapse, { column: column.label })} onClick={() => toggle(column.id)}>\n <FoundationIcon name={closed ? 'chevron-right' : 'chevron-down'} />\n </button>\n <h3>{column.label}</h3>\n <span className='foundation-count'>{inColumn.length}{column.limit > 0 ? ` / ${column.limit}` : ''}</span>\n {over && <span className='foundation-chip' data-tone='danger'><FoundationIcon name='alert' />{formatText(strings.boardWipExceeded, { limit: column.limit })}</span>}\n </header>\n {!closed && (\n <ul className='foundation-board-cards'>\n {inColumn.length === 0 && <li className='foundation-count'>{strings.boardNoCards}</li>}\n {inColumn.map(card => (\n <li key={card.id} className='foundation-board-card' draggable={!locked} onDragStart={() => setDragging(card.id)} onDragEnd={() => setDragging(undefined)}>\n <strong>{card.title}</strong>\n {card.assignee && <span className='foundation-count'><FoundationIcon name='user' /> {card.assignee}</span>}\n {card.fields.map(field => <span key={field.label} className='foundation-board-field'><span className='foundation-count'>{field.label}</span> {field.value}</span>)}\n {card.badges.length > 0 && <span className='foundation-board-badges'>{card.badges.map(badge => <span key={badge} className='foundation-chip' data-tone='neutral'>{badge}</span>)}</span>}\n {!locked && (\n <select className='foundation-board-move' aria-label={formatText(strings.boardMoveCard, { title: card.title })} value={column.id} onChange={event => move(card.id, event.target.value)}>\n <option value={column.id} disabled>{strings.boardMoveTo}</option>\n {columns.filter(other => other.id !== column.id).map(other => <option key={other.id} value={other.id}>{other.label}</option>)}\n </select>\n )}\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n })}\n </div>\n </>\n )}\n </FoundationFrame>\n );\n}\n"],"names":["KanbanBoard","element","interactions","bindingOutputs","columns","useMemo","readColumnsOfBoard","properties","supplied","readCards","cards","suppliedKey","JSON","stringify","setCards","useState","collapsed","setCollapsed","Set","announcement","setAnnouncement","dragging","setDragging","strings","readFoundationStrings","state","readComponentState","length","locked","readPermissionRule","useEffect","useValueOutput","map","card","id","column","move","to","find","candidate","target","next","moveCard","formatText","boardMoved","title","label","onChange","drop","event","preventDefault","undefined","toggle","current","has","delete","add","_jsx","FoundationFrame","name","skeleton","ComponentState","Ready","Partial","_jsxs","_Fragment","div","role","aria-live","className","inColumn","cardsOf","closed","over","overLimit","section","data-collapsed","data-over","aria-label","boardColumn","count","onDragOver","onDrop","header","button","type","aria-expanded","boardExpand","boardCollapse","onClick","FoundationIcon","h3","span","limit","data-tone","boardWipExceeded","ul","li","boardNoCards","draggable","onDragStart","onDragEnd","strong","assignee","fields","field","value","badges","badge","select","boardMoveCard","option","disabled","boardMoveTo","filter","other"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotificationsButton.d.ts","sourceRoot":"","sources":["../../../foundation/NotificationsButton.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAY/D,wBAAgB,mBAAmB,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,wBAAwB,+BAYtF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { FoundationIcon } from './FoundationIcon.js';
|
|
3
|
+
import { formatNumber, readLocale, NumberFormat } from './formatting.js';
|
|
4
|
+
import { readFoundationStrings, formatText } from './foundationStrings.js';
|
|
5
|
+
|
|
6
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
7
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
8
|
+
/**
|
|
9
|
+
* The `notificationsButton` component: the bell of the topbar, with the unread count.
|
|
10
|
+
*
|
|
11
|
+
* `count` is the unread number - bind it to a query - and the button says it in words ("3 unread") as well as in the badge, which is hidden from
|
|
12
|
+
* assistive technology so it is not read twice. Pressing it runs the behaviors attached to the element, which open whatever the application shows its
|
|
13
|
+
* notifications in. Counts above 99 read "99+" in the badge and in full in the words.
|
|
14
|
+
*/ function NotificationsButton({ element, interactions }) {
|
|
15
|
+
const strings = readFoundationStrings(element);
|
|
16
|
+
const count = typeof element.properties.count === 'number' && element.properties.count > 0 ? Math.floor(element.properties.count) : 0;
|
|
17
|
+
const spoken = count > 0 ? formatText(strings.notificationsCount, {
|
|
18
|
+
count: formatNumber(count, readLocale(element), NumberFormat.Number, undefined, 0)
|
|
19
|
+
}) : strings.notificationsNone;
|
|
20
|
+
return /*#__PURE__*/ jsxs("button", {
|
|
21
|
+
type: "button",
|
|
22
|
+
className: "foundation foundation-notifications",
|
|
23
|
+
"data-scene-id": element.id,
|
|
24
|
+
onClick: interactions?.onClick,
|
|
25
|
+
children: [
|
|
26
|
+
/*#__PURE__*/ jsx(FoundationIcon, {
|
|
27
|
+
name: "alert"
|
|
28
|
+
}),
|
|
29
|
+
/*#__PURE__*/ jsx("span", {
|
|
30
|
+
className: "foundation-visually-hidden",
|
|
31
|
+
children: `${strings.notificationsLabel}: ${spoken}`
|
|
32
|
+
}),
|
|
33
|
+
count > 0 && /*#__PURE__*/ jsx("span", {
|
|
34
|
+
className: "foundation-notifications-badge",
|
|
35
|
+
"aria-hidden": "true",
|
|
36
|
+
children: count > 99 ? '99+' : count
|
|
37
|
+
})
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { NotificationsButton };
|
|
43
|
+
//# sourceMappingURL=NotificationsButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotificationsButton.js","sources":["../../../foundation/NotificationsButton.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { FoundationIcon } from './FoundationIcon';\nimport { formatNumber, readLocale, NumberFormat } from './formatting';\nimport { formatText, readFoundationStrings } from './foundationStrings';\n\n/**\n * The `notificationsButton` component: the bell of the topbar, with the unread count.\n *\n * `count` is the unread number - bind it to a query - and the button says it in words (\"3 unread\") as well as in the badge, which is hidden from\n * assistive technology so it is not read twice. Pressing it runs the behaviors attached to the element, which open whatever the application shows its\n * notifications in. Counts above 99 read \"99+\" in the badge and in full in the words.\n */\nexport function NotificationsButton({ element, interactions }: RegisteredComponentProps) {\n const strings = readFoundationStrings(element);\n const count = typeof element.properties.count === 'number' && element.properties.count > 0 ? Math.floor(element.properties.count) : 0;\n const spoken = count > 0 ? formatText(strings.notificationsCount, { count: formatNumber(count, readLocale(element), NumberFormat.Number, undefined, 0) }) : strings.notificationsNone;\n\n return (\n <button type='button' className='foundation foundation-notifications' data-scene-id={element.id} onClick={interactions?.onClick}>\n <FoundationIcon name='alert' />\n <span className='foundation-visually-hidden'>{`${strings.notificationsLabel}: ${spoken}`}</span>\n {count > 0 && <span className='foundation-notifications-badge' aria-hidden='true'>{count > 99 ? '99+' : count}</span>}\n </button>\n );\n}\n"],"names":["NotificationsButton","element","interactions","strings","readFoundationStrings","count","properties","Math","floor","spoken","formatText","notificationsCount","formatNumber","readLocale","NumberFormat","Number","undefined","notificationsNone","_jsxs","button","type","className","data-scene-id","id","onClick","_jsx","FoundationIcon","name","span","notificationsLabel","aria-hidden"],"mappings":";;;;;AAAA;AACA;AAOA;;;;;;AAMC,IACM,SAASA,mBAAAA,CAAoB,EAAEC,OAAO,EAAEC,YAAY,EAA4B,EAAA;AACnF,IAAA,MAAMC,UAAUC,qBAAAA,CAAsBH,OAAAA,CAAAA;IACtC,MAAMI,KAAAA,GAAQ,OAAOJ,OAAAA,CAAQK,UAAU,CAACD,KAAK,KAAK,YAAYJ,OAAAA,CAAQK,UAAU,CAACD,KAAK,GAAG,IAAIE,IAAAA,CAAKC,KAAK,CAACP,OAAAA,CAAQK,UAAU,CAACD,KAAK,CAAA,GAAI,CAAA;AACpI,IAAA,MAAMI,SAASJ,KAAAA,GAAQ,CAAA,GAAIK,UAAAA,CAAWP,OAAAA,CAAQQ,kBAAkB,EAAE;AAAEN,QAAAA,KAAAA,EAAOO,aAAaP,KAAAA,EAAOQ,UAAAA,CAAWZ,UAAUa,YAAAA,CAAaC,MAAM,EAAEC,SAAAA,EAAW,CAAA;AAAG,KAAA,CAAA,GAAKb,QAAQc,iBAAiB;AAErL,IAAA,qBACIC,IAAA,CAACC,QAAAA,EAAAA;QAAOC,IAAAA,EAAK,QAAA;QAASC,SAAAA,EAAU,qCAAA;AAAsCC,QAAAA,eAAAA,EAAerB,QAAQsB,EAAE;AAAEC,QAAAA,OAAAA,EAAStB,YAAAA,EAAcsB,OAAAA;;0BACpHC,GAAA,CAACC,cAAAA,EAAAA;gBAAeC,IAAAA,EAAK;;0BACrBF,GAAA,CAACG,MAAAA,EAAAA;gBAAKP,SAAAA,EAAU,4BAAA;AAA8B,gBAAA,QAAA,EAAA,CAAA,EAAGlB,OAAAA,CAAQ0B,kBAAkB,CAAC,EAAE,EAAEpB,MAAAA,CAAAA;;AAC/EJ,YAAAA,KAAAA,GAAQ,mBAAKoB,GAAA,CAACG,MAAAA,EAAAA;gBAAKP,SAAAA,EAAU,gCAAA;gBAAiCS,aAAAA,EAAY,MAAA;AAAQzB,gBAAAA,QAAAA,EAAAA,KAAAA,GAAQ,KAAK,KAAA,GAAQA;;;;AAGpH;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubNavigation.d.ts","sourceRoot":"","sources":["../../../foundation/SubNavigation.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAkB,MAAM,qBAAqB,CAAC;AAgB/E,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,EAAE,wBAAwB,+BA4BhG"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useValueOutput } from '@cratis/scene.react';
|
|
4
|
+
import { readOptionalString } from '../shell/elementProperties.js';
|
|
5
|
+
import { readTabs, activeTab } from './tabModel.js';
|
|
6
|
+
import { readComponentState, ComponentState } from './ComponentState.js';
|
|
7
|
+
import { readFoundationStrings } from './foundationStrings.js';
|
|
8
|
+
import { FoundationFrame } from './StateFrame.js';
|
|
9
|
+
import { useUrlState } from './urlState.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The `subNavigation` component: a module's own sections as a tab bar or a left rail.
|
|
13
|
+
*
|
|
14
|
+
* `items` name the sections (id, label, optional count badge), `orientation` is `horizontal` (tabs, default) or `vertical` (a left rail), and
|
|
15
|
+
* `urlKey` keeps the active section in the address so a deep link restores it. It is a navigation landmark, the current section carries
|
|
16
|
+
* `aria-current="page"`, and choosing a section only changes the section: the shell around it keeps its state, which is what makes it a
|
|
17
|
+
* sub-navigation rather than a page change. The id of the active section is the `value` output, which the module's content binds to.
|
|
18
|
+
*/ function SubNavigation({ element, interactions, bindingOutputs }) {
|
|
19
|
+
const items = useMemo(()=>readTabs(element.properties.items), [
|
|
20
|
+
element.properties.items
|
|
21
|
+
]);
|
|
22
|
+
const [requested, setRequested] = useUrlState(readOptionalString(element, 'urlKey'), readOptionalString(element, 'activeItem'));
|
|
23
|
+
const active = activeTab(items, requested);
|
|
24
|
+
const strings = readFoundationStrings(element);
|
|
25
|
+
const state = readComponentState(element, items.length > 0);
|
|
26
|
+
useValueOutput(bindingOutputs, active);
|
|
27
|
+
return /*#__PURE__*/ jsx(FoundationFrame, {
|
|
28
|
+
element: element,
|
|
29
|
+
interactions: interactions,
|
|
30
|
+
name: "sub-navigation",
|
|
31
|
+
state: state,
|
|
32
|
+
skeleton: [
|
|
33
|
+
50
|
|
34
|
+
],
|
|
35
|
+
children: state !== ComponentState.Loading && /*#__PURE__*/ jsx("nav", {
|
|
36
|
+
"aria-label": readOptionalString(element, 'label') ?? strings.subNavLabel,
|
|
37
|
+
className: "foundation-subnav",
|
|
38
|
+
"data-orientation": element.properties.orientation === 'vertical' ? 'vertical' : 'horizontal',
|
|
39
|
+
children: /*#__PURE__*/ jsx("ul", {
|
|
40
|
+
children: items.map((item)=>/*#__PURE__*/ jsx("li", {
|
|
41
|
+
children: /*#__PURE__*/ jsxs("a", {
|
|
42
|
+
href: `?${new URLSearchParams({
|
|
43
|
+
[readOptionalString(element, 'urlKey') ?? 'section']: item.id
|
|
44
|
+
}).toString()}`,
|
|
45
|
+
"aria-current": item.id === active ? 'page' : undefined,
|
|
46
|
+
"aria-disabled": item.disabled || undefined,
|
|
47
|
+
className: "foundation-subnav-link",
|
|
48
|
+
onClick: (event)=>{
|
|
49
|
+
event.preventDefault();
|
|
50
|
+
if (!item.disabled) {
|
|
51
|
+
setRequested(item.id);
|
|
52
|
+
interactions?.onSelect?.();
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
children: [
|
|
56
|
+
item.label,
|
|
57
|
+
item.badge !== undefined && /*#__PURE__*/ jsx("span", {
|
|
58
|
+
className: "foundation-tab-badge",
|
|
59
|
+
children: item.badge
|
|
60
|
+
})
|
|
61
|
+
]
|
|
62
|
+
})
|
|
63
|
+
}, item.id))
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { SubNavigation };
|
|
70
|
+
//# sourceMappingURL=SubNavigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubNavigation.js","sources":["../../../foundation/SubNavigation.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useMemo } from 'react';\nimport { RegisteredComponentProps, useValueOutput } from '@cratis/scene.react';\nimport { readOptionalString } from '../shell/elementProperties';\nimport { activeTab, readTabs } from './tabModel';\nimport { ComponentState, readComponentState } from './ComponentState';\nimport { readFoundationStrings } from './foundationStrings';\nimport { FoundationFrame } from './StateFrame';\nimport { useUrlState } from './urlState';\n\n/**\n * The `subNavigation` component: a module's own sections as a tab bar or a left rail.\n *\n * `items` name the sections (id, label, optional count badge), `orientation` is `horizontal` (tabs, default) or `vertical` (a left rail), and\n * `urlKey` keeps the active section in the address so a deep link restores it. It is a navigation landmark, the current section carries\n * `aria-current=\"page\"`, and choosing a section only changes the section: the shell around it keeps its state, which is what makes it a\n * sub-navigation rather than a page change. The id of the active section is the `value` output, which the module's content binds to.\n */\nexport function SubNavigation({ element, interactions, bindingOutputs }: RegisteredComponentProps) {\n const items = useMemo(() => readTabs(element.properties.items), [element.properties.items]);\n const [requested, setRequested] = useUrlState(readOptionalString(element, 'urlKey'), readOptionalString(element, 'activeItem'));\n const active = activeTab(items, requested);\n const strings = readFoundationStrings(element);\n const state = readComponentState(element, items.length > 0);\n\n useValueOutput(bindingOutputs, active);\n\n return (\n <FoundationFrame element={element} interactions={interactions} name='sub-navigation' state={state} skeleton={[50]}>\n {state !== ComponentState.Loading && (\n <nav aria-label={readOptionalString(element, 'label') ?? strings.subNavLabel} className='foundation-subnav' data-orientation={element.properties.orientation === 'vertical' ? 'vertical' : 'horizontal'}>\n <ul>\n {items.map(item => (\n <li key={item.id}>\n <a href={`?${new URLSearchParams({ [readOptionalString(element, 'urlKey') ?? 'section']: item.id }).toString()}`} aria-current={item.id === active ? 'page' : undefined}\n aria-disabled={item.disabled || undefined} className='foundation-subnav-link'\n onClick={event => { event.preventDefault(); if (!item.disabled) { setRequested(item.id); interactions?.onSelect?.(); } }}>\n {item.label}{item.badge !== undefined && <span className='foundation-tab-badge'>{item.badge}</span>}\n </a>\n </li>\n ))}\n </ul>\n </nav>\n )}\n </FoundationFrame>\n );\n}\n"],"names":["SubNavigation","element","interactions","bindingOutputs","items","useMemo","readTabs","properties","requested","setRequested","useUrlState","readOptionalString","active","activeTab","strings","readFoundationStrings","state","readComponentState","length","useValueOutput","_jsx","FoundationFrame","name","skeleton","ComponentState","Loading","nav","aria-label","subNavLabel","className","data-orientation","orientation","ul","map","item","li","_jsxs","a","href","URLSearchParams","id","toString","aria-current","undefined","aria-disabled","disabled","onClick","event","preventDefault","onSelect","label","badge","span"],"mappings":";;;;;;;;;;AAYA;;;;;;;IAQO,SAASA,aAAAA,CAAc,EAAEC,OAAO,EAAEC,YAAY,EAAEC,cAAc,EAA4B,EAAA;IAC7F,MAAMC,KAAAA,GAAQC,QAAQ,IAAMC,QAAAA,CAASL,QAAQM,UAAU,CAACH,KAAK,CAAA,EAAG;QAACH,OAAAA,CAAQM,UAAU,CAACH;AAAM,KAAA,CAAA;IAC1F,MAAM,CAACI,WAAWC,YAAAA,CAAa,GAAGC,YAAYC,kBAAAA,CAAmBV,OAAAA,EAAS,QAAA,CAAA,EAAWU,kBAAAA,CAAmBV,OAAAA,EAAS,YAAA,CAAA,CAAA;IACjH,MAAMW,MAAAA,GAASC,UAAUT,KAAAA,EAAOI,SAAAA,CAAAA;AAChC,IAAA,MAAMM,UAAUC,qBAAAA,CAAsBd,OAAAA,CAAAA;AACtC,IAAA,MAAMe,KAAAA,GAAQC,kBAAAA,CAAmBhB,OAAAA,EAASG,KAAAA,CAAMc,MAAM,GAAG,CAAA,CAAA;AAEzDC,IAAAA,cAAAA,CAAehB,cAAAA,EAAgBS,MAAAA,CAAAA;AAE/B,IAAA,qBACIQ,GAAA,CAACC,eAAAA,EAAAA;QAAgBpB,OAAAA,EAASA,OAAAA;QAASC,YAAAA,EAAcA,YAAAA;QAAcoB,IAAAA,EAAK,gBAAA;QAAiBN,KAAAA,EAAOA,KAAAA;QAAOO,QAAAA,EAAU;AAAC,YAAA;AAAG,SAAA;kBAC5GP,KAAAA,KAAUQ,cAAAA,CAAeC,OAAO,kBAC7BL,GAAA,CAACM,KAAAA,EAAAA;AAAIC,YAAAA,YAAAA,EAAYhB,kBAAAA,CAAmBV,OAAAA,EAAS,OAAA,CAAA,IAAYa,OAAAA,CAAQc,WAAW;YAAEC,SAAAA,EAAU,mBAAA;AAAoBC,YAAAA,kBAAAA,EAAkB7B,QAAQM,UAAU,CAACwB,WAAW,KAAK,aAAa,UAAA,GAAa,YAAA;AACvL,YAAA,QAAA,gBAAAX,GAAA,CAACY,IAAAA,EAAAA;AACI5B,gBAAAA,QAAAA,EAAAA,KAAAA,CAAM6B,GAAG,CAACC,CAAAA,IAAAA,iBACPd,GAAA,CAACe,IAAAA,EAAAA;AACG,wBAAA,QAAA,gBAAAC,IAAA,CAACC,GAAAA,EAAAA;AAAEC,4BAAAA,IAAAA,EAAM,CAAC,CAAC,EAAE,IAAIC,eAAAA,CAAgB;AAAE,gCAAA,CAAC5B,mBAAmBV,OAAAA,EAAS,QAAA,CAAA,IAAa,SAAA,GAAYiC,KAAKM;AAAG,6BAAA,CAAA,CAAGC,QAAQ,EAAA,CAAA,CAAI;AAAEC,4BAAAA,cAAAA,EAAcR,IAAAA,CAAKM,EAAE,KAAK5B,MAAAA,GAAS,MAAA,GAAS+B,SAAAA;4BAC1JC,eAAAA,EAAeV,IAAAA,CAAKW,QAAQ,IAAIF,SAAAA;4BAAWd,SAAAA,EAAU,wBAAA;AACrDiB,4BAAAA,OAAAA,EAASC,CAAAA,KAAAA,GAAAA;AAAWA,gCAAAA,KAAAA,CAAMC,cAAc,EAAA;gCAAI,IAAI,CAACd,IAAAA,CAAKW,QAAQ,EAAE;AAAEpC,oCAAAA,YAAAA,CAAayB,KAAKM,EAAE,CAAA;oCAAGtC,YAAAA,EAAc+C,QAAAA,IAAAA;AAAc,gCAAA;AAAE,4BAAA,CAAA;;AACtHf,gCAAAA,IAAAA,CAAKgB,KAAK;gCAAEhB,IAAAA,CAAKiB,KAAK,KAAKR,SAAAA,kBAAavB,GAAA,CAACgC,MAAAA,EAAAA;oCAAKvB,SAAAA,EAAU,sBAAA;AAAwBK,oCAAAA,QAAAA,EAAAA,IAAAA,CAAKiB;;;;AAJrFjB,qBAAAA,EAAAA,IAAAA,CAAKM,EAAE,CAAA;;;;AAa5C;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabSet.d.ts","sourceRoot":"","sources":["../../../foundation/TabSet.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAkB,MAAM,qBAAqB,CAAC;AAgB/E,wBAAgB,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,wBAAwB,+BA4ChG"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useMemo, useRef } from 'react';
|
|
3
|
+
import { useValueOutput } from '@cratis/scene.react';
|
|
4
|
+
import { readOptionalString } from '../shell/elementProperties.js';
|
|
5
|
+
import { readTabs, activeTab, stepTab } from './tabModel.js';
|
|
6
|
+
import { readComponentState, ComponentState } from './ComponentState.js';
|
|
7
|
+
import { readFoundationStrings } from './foundationStrings.js';
|
|
8
|
+
import { FoundationFrame } from './StateFrame.js';
|
|
9
|
+
import { useUrlState } from './urlState.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The `tabSet` component: a set of tabs, each showing the content filed under its id in the element's slots.
|
|
13
|
+
*
|
|
14
|
+
* `tabs` name the tabs (id, label, optional count badge, disabled); the content of tab `overview` is the slot `overview`. It follows the
|
|
15
|
+
* ARIA tabs pattern - arrows, Home and End move and select, the active tab is the one tab stop, each panel is labelled by its tab - and the
|
|
16
|
+
* active tab is kept in the address under `urlKey` when one is given, so a deep link and a refresh restore it. The id of the active tab is the
|
|
17
|
+
* `value` output. The tabs a record page offers (Overview, Related, Files, History) are configurable by changing this property.
|
|
18
|
+
*/ function TabSet({ element, interactions, slots, bindingOutputs }) {
|
|
19
|
+
const tabs = useMemo(()=>readTabs(element.properties.tabs), [
|
|
20
|
+
element.properties.tabs
|
|
21
|
+
]);
|
|
22
|
+
const [requested, setRequested] = useUrlState(readOptionalString(element, 'urlKey'), readOptionalString(element, 'activeTab'));
|
|
23
|
+
const active = activeTab(tabs, requested);
|
|
24
|
+
const strings = readFoundationStrings(element);
|
|
25
|
+
const state = readComponentState(element, tabs.length > 0);
|
|
26
|
+
const list = useRef(null);
|
|
27
|
+
useValueOutput(bindingOutputs, active);
|
|
28
|
+
const choose = (id, focus = false)=>{
|
|
29
|
+
if (id === undefined) return;
|
|
30
|
+
setRequested(id);
|
|
31
|
+
interactions?.onSelect?.();
|
|
32
|
+
if (focus) requestAnimationFrame(()=>list.current?.querySelector(`[data-tab="${CSS.escape(id)}"]`)?.focus());
|
|
33
|
+
};
|
|
34
|
+
const move = (event)=>{
|
|
35
|
+
const direction = {
|
|
36
|
+
ArrowRight: 'next',
|
|
37
|
+
ArrowDown: 'next',
|
|
38
|
+
ArrowLeft: 'previous',
|
|
39
|
+
ArrowUp: 'previous',
|
|
40
|
+
Home: 'first',
|
|
41
|
+
End: 'last'
|
|
42
|
+
}[event.key];
|
|
43
|
+
if (direction === undefined) return;
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
choose(stepTab(tabs, active, direction), true);
|
|
46
|
+
};
|
|
47
|
+
return /*#__PURE__*/ jsx(FoundationFrame, {
|
|
48
|
+
element: element,
|
|
49
|
+
interactions: interactions,
|
|
50
|
+
name: "tab-set",
|
|
51
|
+
state: state,
|
|
52
|
+
skeleton: [
|
|
53
|
+
60,
|
|
54
|
+
100
|
|
55
|
+
],
|
|
56
|
+
children: state !== ComponentState.Loading && /*#__PURE__*/ jsxs(Fragment, {
|
|
57
|
+
children: [
|
|
58
|
+
/*#__PURE__*/ jsx("div", {
|
|
59
|
+
ref: list,
|
|
60
|
+
role: "tablist",
|
|
61
|
+
"aria-label": readOptionalString(element, 'label') ?? strings.tabsLabel,
|
|
62
|
+
className: "foundation-tabs",
|
|
63
|
+
onKeyDown: move,
|
|
64
|
+
children: tabs.map((tab)=>/*#__PURE__*/ jsxs("button", {
|
|
65
|
+
id: `${element.id}-tab-${tab.id}`,
|
|
66
|
+
"data-tab": tab.id,
|
|
67
|
+
type: "button",
|
|
68
|
+
role: "tab",
|
|
69
|
+
className: "foundation-tab",
|
|
70
|
+
"aria-selected": tab.id === active,
|
|
71
|
+
"aria-controls": `${element.id}-panel-${tab.id}`,
|
|
72
|
+
tabIndex: tab.id === active ? 0 : -1,
|
|
73
|
+
disabled: tab.disabled,
|
|
74
|
+
onClick: ()=>choose(tab.id),
|
|
75
|
+
children: [
|
|
76
|
+
tab.label,
|
|
77
|
+
tab.badge !== undefined && /*#__PURE__*/ jsx("span", {
|
|
78
|
+
className: "foundation-tab-badge",
|
|
79
|
+
children: tab.badge
|
|
80
|
+
})
|
|
81
|
+
]
|
|
82
|
+
}, tab.id))
|
|
83
|
+
}),
|
|
84
|
+
tabs.map((tab)=>/*#__PURE__*/ jsx("div", {
|
|
85
|
+
id: `${element.id}-panel-${tab.id}`,
|
|
86
|
+
role: "tabpanel",
|
|
87
|
+
"aria-labelledby": `${element.id}-tab-${tab.id}`,
|
|
88
|
+
hidden: tab.id !== active,
|
|
89
|
+
tabIndex: 0,
|
|
90
|
+
className: "foundation-tab-panel",
|
|
91
|
+
children: tab.id === active ? slots?.[tab.id] : undefined
|
|
92
|
+
}, tab.id))
|
|
93
|
+
]
|
|
94
|
+
})
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { TabSet };
|
|
99
|
+
//# sourceMappingURL=TabSet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabSet.js","sources":["../../../foundation/TabSet.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { KeyboardEvent, useMemo, useRef } from 'react';\nimport { RegisteredComponentProps, useValueOutput } from '@cratis/scene.react';\nimport { readOptionalString } from '../shell/elementProperties';\nimport { activeTab, readTabs, stepTab } from './tabModel';\nimport { ComponentState, readComponentState } from './ComponentState';\nimport { readFoundationStrings } from './foundationStrings';\nimport { FoundationFrame } from './StateFrame';\nimport { useUrlState } from './urlState';\n\n/**\n * The `tabSet` component: a set of tabs, each showing the content filed under its id in the element's slots.\n *\n * `tabs` name the tabs (id, label, optional count badge, disabled); the content of tab `overview` is the slot `overview`. It follows the\n * ARIA tabs pattern - arrows, Home and End move and select, the active tab is the one tab stop, each panel is labelled by its tab - and the\n * active tab is kept in the address under `urlKey` when one is given, so a deep link and a refresh restore it. The id of the active tab is the\n * `value` output. The tabs a record page offers (Overview, Related, Files, History) are configurable by changing this property.\n */\nexport function TabSet({ element, interactions, slots, bindingOutputs }: RegisteredComponentProps) {\n const tabs = useMemo(() => readTabs(element.properties.tabs), [element.properties.tabs]);\n const [requested, setRequested] = useUrlState(readOptionalString(element, 'urlKey'), readOptionalString(element, 'activeTab'));\n const active = activeTab(tabs, requested);\n const strings = readFoundationStrings(element);\n const state = readComponentState(element, tabs.length > 0);\n const list = useRef<HTMLDivElement>(null);\n\n useValueOutput(bindingOutputs, active);\n\n const choose = (id: string | undefined, focus = false) => {\n if (id === undefined) return;\n setRequested(id);\n interactions?.onSelect?.();\n if (focus) requestAnimationFrame(() => list.current?.querySelector<HTMLElement>(`[data-tab=\"${CSS.escape(id)}\"]`)?.focus());\n };\n const move = (event: KeyboardEvent) => {\n const direction = { ArrowRight: 'next', ArrowDown: 'next', ArrowLeft: 'previous', ArrowUp: 'previous', Home: 'first', End: 'last' }[event.key] as 'next' | 'previous' | 'first' | 'last' | undefined;\n if (direction === undefined) return;\n event.preventDefault();\n choose(stepTab(tabs, active, direction), true);\n };\n\n return (\n <FoundationFrame element={element} interactions={interactions} name='tab-set' state={state} skeleton={[60, 100]}>\n {state !== ComponentState.Loading && (\n <>\n <div ref={list} role='tablist' aria-label={readOptionalString(element, 'label') ?? strings.tabsLabel} className='foundation-tabs' onKeyDown={move}>\n {tabs.map(tab => (\n <button key={tab.id} id={`${element.id}-tab-${tab.id}`} data-tab={tab.id} type='button' role='tab' className='foundation-tab' aria-selected={tab.id === active}\n aria-controls={`${element.id}-panel-${tab.id}`} tabIndex={tab.id === active ? 0 : -1} disabled={tab.disabled} onClick={() => choose(tab.id)}>\n {tab.label}{tab.badge !== undefined && <span className='foundation-tab-badge'>{tab.badge}</span>}\n </button>\n ))}\n </div>\n {tabs.map(tab => (\n <div key={tab.id} id={`${element.id}-panel-${tab.id}`} role='tabpanel' aria-labelledby={`${element.id}-tab-${tab.id}`} hidden={tab.id !== active} tabIndex={0} className='foundation-tab-panel'>\n {tab.id === active ? slots?.[tab.id] : undefined}\n </div>\n ))}\n </>\n )}\n </FoundationFrame>\n );\n}\n"],"names":["TabSet","element","interactions","slots","bindingOutputs","tabs","useMemo","readTabs","properties","requested","setRequested","useUrlState","readOptionalString","active","activeTab","strings","readFoundationStrings","state","readComponentState","length","list","useRef","useValueOutput","choose","id","focus","undefined","onSelect","requestAnimationFrame","current","querySelector","CSS","escape","move","event","direction","ArrowRight","ArrowDown","ArrowLeft","ArrowUp","Home","End","key","preventDefault","stepTab","_jsx","FoundationFrame","name","skeleton","ComponentState","Loading","_jsxs","_Fragment","div","ref","role","aria-label","tabsLabel","className","onKeyDown","map","tab","button","data-tab","type","aria-selected","aria-controls","tabIndex","disabled","onClick","label","badge","span","aria-labelledby","hidden"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WizardProgress.d.ts","sourceRoot":"","sources":["../../../foundation/WizardProgress.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAkB,MAAM,qBAAqB,CAAC;AA2C/E,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,wBAAwB,+BA6DxG"}
|