@unofficialbox/box-open-elements 0.20.0 → 0.21.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/components/actions/menu-item.d.ts +2 -0
- package/dist/components/actions/menu-item.js +4 -0
- package/dist/components/collections/card.js +6 -0
- package/dist/components/collections/result-blocks.js +4 -1
- package/dist/components/feedback/alert.d.ts +2 -0
- package/dist/components/feedback/alert.js +17 -13
- package/dist/components/feedback/toast.d.ts +10 -1
- package/dist/components/feedback/toast.js +69 -27
- package/dist/components/forms/number-input.d.ts +1 -0
- package/dist/components/forms/number-input.js +9 -6
- package/dist/components/forms/search-field.js +16 -0
- package/dist/components/overlays/context-menu.d.ts +2 -0
- package/dist/components/overlays/context-menu.js +7 -0
- package/dist/components/overlays/dialog.js +19 -3
- package/dist/components/overlays/popover.js +6 -1
- package/dist/element-maps.d.ts +11 -1
- package/dist/foundations/a11y/announcer.d.ts +12 -0
- package/dist/foundations/a11y/announcer.js +75 -0
- package/dist/foundations/a11y/focus.js +46 -25
- package/dist/foundations/a11y/index.d.ts +2 -0
- package/dist/foundations/a11y/index.js +1 -0
- package/dist/foundations/icons/box-iconography.d.ts +472 -472
- package/dist/foundations/icons/box-iconography.generated.d.ts +1151 -679
- package/dist/foundations/icons/box-iconography.generated.js +1006 -3588
- package/dist/foundations/icons/glyphs/index.d.ts +1 -0
- package/dist/foundations/icons/glyphs/index.js +2 -0
- package/dist/foundations/icons/glyphs/package.json +1 -0
- package/dist/foundations/overlay/positioning.js +7 -0
- package/dist/foundations/status/index.d.ts +1 -1
- package/dist/foundations/status/index.js +8 -6
- package/dist/foundations/tokens/box-dark.js +4 -1
- package/dist/foundations/tokens/box-defaults.js +3 -0
- package/dist/foundations/tokens/registry.d.ts +3 -0
- package/dist/foundations/tokens/registry.js +3 -0
- package/dist/foundations/tokens/types.d.ts +3 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/patterns/agent-chat/agent-chat.js +12 -4
- package/dist/patterns/call-console/call-console.d.ts +3 -0
- package/dist/patterns/call-console/call-console.js +114 -20
- package/dist/patterns/content-explorer/adapters/action-menu.js +7 -5
- package/dist/patterns/content-explorer/adapters/toolbar.js +6 -2
- package/dist/patterns/file-request/file-request-builder.js +3 -0
- package/dist/patterns/flow-builder/flow-builder.d.ts +48 -0
- package/dist/patterns/flow-builder/flow-builder.js +200 -0
- package/dist/patterns/flow-builder/index.d.ts +3 -0
- package/dist/patterns/flow-builder/index.js +3 -0
- package/dist/patterns/flow-builder/model.d.ts +33 -0
- package/dist/patterns/flow-builder/model.js +28 -0
- package/dist/patterns/flow-builder/primitives.d.ts +47 -0
- package/dist/patterns/flow-builder/primitives.js +192 -0
- package/dist/patterns/lineage/lineage-graph.js +26 -6
- package/dist/patterns/notifications/notification-inbox.js +19 -3
- package/dist/patterns/preview/annotation-inspector.js +2 -2
- package/dist/patterns/undo/index.d.ts +19 -0
- package/dist/patterns/undo/index.js +106 -0
- package/package.json +11 -2
|
@@ -17,6 +17,8 @@ const elementStyles = `
|
|
|
17
17
|
|
|
18
18
|
:host {
|
|
19
19
|
display: block;
|
|
20
|
+
min-inline-size: 0;
|
|
21
|
+
container: boe-notification-inbox / inline-size;
|
|
20
22
|
color: inherit;
|
|
21
23
|
font: inherit;
|
|
22
24
|
}
|
|
@@ -29,6 +31,7 @@ const elementStyles = `
|
|
|
29
31
|
|
|
30
32
|
[part="panel"] {
|
|
31
33
|
display: grid;
|
|
34
|
+
grid-template-columns: minmax(0, 1fr);
|
|
32
35
|
grid-template-rows: auto auto 1fr;
|
|
33
36
|
gap: ${boePanel.gap};
|
|
34
37
|
padding: ${boePanel.padding};
|
|
@@ -40,11 +43,13 @@ const elementStyles = `
|
|
|
40
43
|
|
|
41
44
|
[part="header"] {
|
|
42
45
|
display: flex;
|
|
46
|
+
flex-wrap: wrap;
|
|
43
47
|
align-items: center;
|
|
44
48
|
gap: 0.5rem;
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
[part="title"] {
|
|
52
|
+
overflow-wrap: anywhere;
|
|
48
53
|
margin: 0;
|
|
49
54
|
font: inherit;
|
|
50
55
|
font-size: 1.05rem;
|
|
@@ -56,7 +61,7 @@ const elementStyles = `
|
|
|
56
61
|
padding: 0.1rem 0.45rem;
|
|
57
62
|
border-radius: 999px;
|
|
58
63
|
background: color-mix(in srgb, var(--boe-token-surface-status-surface-error, #ed3757) 14%, transparent);
|
|
59
|
-
color:
|
|
64
|
+
color: var(--boe-token-text-status-text-error, #b92340);
|
|
60
65
|
font-size: 0.72rem;
|
|
61
66
|
font-weight: 700;
|
|
62
67
|
}
|
|
@@ -134,7 +139,7 @@ const elementStyles = `
|
|
|
134
139
|
text-transform: none;
|
|
135
140
|
letter-spacing: normal;
|
|
136
141
|
font-size: 0.7rem;
|
|
137
|
-
color:
|
|
142
|
+
color: var(--boe-token-text-status-text-error, #b92340);
|
|
138
143
|
}
|
|
139
144
|
|
|
140
145
|
[part="items"] {
|
|
@@ -147,7 +152,7 @@ const elementStyles = `
|
|
|
147
152
|
|
|
148
153
|
[part="item"] {
|
|
149
154
|
display: grid;
|
|
150
|
-
grid-template-columns: auto 1fr auto;
|
|
155
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
151
156
|
gap: 0.5rem;
|
|
152
157
|
align-items: start;
|
|
153
158
|
padding: 0.5rem 0.55rem;
|
|
@@ -174,6 +179,7 @@ const elementStyles = `
|
|
|
174
179
|
|
|
175
180
|
[part="item-body"] {
|
|
176
181
|
display: grid;
|
|
182
|
+
overflow-wrap: anywhere;
|
|
177
183
|
gap: 0.15rem;
|
|
178
184
|
min-inline-size: 0;
|
|
179
185
|
}
|
|
@@ -223,6 +229,7 @@ const elementStyles = `
|
|
|
223
229
|
|
|
224
230
|
[part="item-actions"] {
|
|
225
231
|
display: flex;
|
|
232
|
+
flex-wrap: wrap;
|
|
226
233
|
gap: 0.25rem;
|
|
227
234
|
}
|
|
228
235
|
|
|
@@ -251,6 +258,15 @@ const elementStyles = `
|
|
|
251
258
|
text-align: center;
|
|
252
259
|
}
|
|
253
260
|
|
|
261
|
+
@container boe-notification-inbox (max-width: 32rem) {
|
|
262
|
+
[part="item"] {
|
|
263
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
264
|
+
}
|
|
265
|
+
[part="item-actions"] {
|
|
266
|
+
grid-column: 2;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
254
270
|
[part="filter"]:focus-visible,
|
|
255
271
|
[part="mark-all"]:focus-visible,
|
|
256
272
|
[part="item-title"]:focus-visible,
|
|
@@ -66,7 +66,7 @@ const elementStyles = `
|
|
|
66
66
|
padding: 0.65rem;
|
|
67
67
|
border-radius: ${boePanel.radius};
|
|
68
68
|
border: 1px solid color-mix(in srgb, var(--boe-token-stroke-stroke, #e8e8e8) 48%, transparent);
|
|
69
|
-
background:
|
|
69
|
+
background: var(--boe-token-surface-surface, #ffffff);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
[part="annotation-header"] {
|
|
@@ -254,7 +254,7 @@ const elementStyles = `
|
|
|
254
254
|
[part="action"][data-tone="primary"] {
|
|
255
255
|
border-color: transparent;
|
|
256
256
|
background: var(--boe-token-surface-surface-brand, #0061d5);
|
|
257
|
-
color: #
|
|
257
|
+
color: var(--boe-token-text-text-on-brand, #ffffff);
|
|
258
258
|
}
|
|
259
259
|
`;
|
|
260
260
|
export class AnnotationInspector extends BaseElement {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Toast } from "../../components/feedback/toast.js";
|
|
2
|
+
/** Remove once and return an idempotent restore preserving the original object's identity. */
|
|
3
|
+
export declare function removeAt<T>(list: T[], index: number): () => void;
|
|
4
|
+
/** Never overwrite a key recreated after removal. */
|
|
5
|
+
export declare function removeKey<T>(map: Record<string, T>, key: string): () => void;
|
|
6
|
+
/** Restore into the current list, preserving intervening edits and clamping the index. */
|
|
7
|
+
export declare function removeFromMapList<T>(map: Record<string, T[]>, key: string, index: number): () => void;
|
|
8
|
+
export interface UndoOffer {
|
|
9
|
+
readonly toast: Toast | null;
|
|
10
|
+
undo(): void;
|
|
11
|
+
dispose(): void;
|
|
12
|
+
}
|
|
13
|
+
export interface UndoOptions {
|
|
14
|
+
container?: HTMLElement;
|
|
15
|
+
duration?: number;
|
|
16
|
+
onRestore?: () => void;
|
|
17
|
+
}
|
|
18
|
+
/** Offer a single document-scoped undo. Hosts call dispose on teardown. SSR-safe. */
|
|
19
|
+
export declare function offerUndo(message: string, restore: () => void, options?: UndoOptions): UndoOffer;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Toast } from "../../components/feedback/toast.js";
|
|
2
|
+
import { announce } from "../../foundations/a11y/index.js";
|
|
3
|
+
/** Remove once and return an idempotent restore preserving the original object's identity. */
|
|
4
|
+
export function removeAt(list, index) {
|
|
5
|
+
if (!Number.isInteger(index) || index < 0 || index >= list.length)
|
|
6
|
+
return () => { };
|
|
7
|
+
const item = list.splice(index, 1)[0];
|
|
8
|
+
let restored = false;
|
|
9
|
+
return () => {
|
|
10
|
+
if (restored)
|
|
11
|
+
return;
|
|
12
|
+
restored = true;
|
|
13
|
+
list.splice(Math.min(index, list.length), 0, item);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Never overwrite a key recreated after removal. */
|
|
17
|
+
export function removeKey(map, key) {
|
|
18
|
+
if (!Object.hasOwn(map, key))
|
|
19
|
+
return () => { };
|
|
20
|
+
const value = map[key];
|
|
21
|
+
delete map[key];
|
|
22
|
+
let restored = false;
|
|
23
|
+
return () => {
|
|
24
|
+
if (restored)
|
|
25
|
+
return;
|
|
26
|
+
restored = true;
|
|
27
|
+
if (!Object.hasOwn(map, key))
|
|
28
|
+
Object.defineProperty(map, key, { value, writable: true, enumerable: true, configurable: true });
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Restore into the current list, preserving intervening edits and clamping the index. */
|
|
32
|
+
export function removeFromMapList(map, key, index) {
|
|
33
|
+
const list = Object.hasOwn(map, key) ? map[key] : undefined;
|
|
34
|
+
if (!list || !Number.isInteger(index) || index < 0 || index >= list.length)
|
|
35
|
+
return () => { };
|
|
36
|
+
const item = list.splice(index, 1)[0];
|
|
37
|
+
if (!list.length)
|
|
38
|
+
delete map[key];
|
|
39
|
+
let restored = false;
|
|
40
|
+
return () => {
|
|
41
|
+
if (restored)
|
|
42
|
+
return;
|
|
43
|
+
restored = true;
|
|
44
|
+
if (!Object.hasOwn(map, key))
|
|
45
|
+
Object.defineProperty(map, key, { value: list, writable: true, enumerable: true, configurable: true });
|
|
46
|
+
const target = map[key];
|
|
47
|
+
target.splice(Math.min(index, target.length), 0, item);
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const offers = new WeakMap();
|
|
51
|
+
/** Offer a single document-scoped undo. Hosts call dispose on teardown. SSR-safe. */
|
|
52
|
+
export function offerUndo(message, restore, options = {}) {
|
|
53
|
+
const doc = options.container?.ownerDocument ?? globalThis.document;
|
|
54
|
+
if (!doc?.body)
|
|
55
|
+
return { toast: null, undo() { }, dispose() { } };
|
|
56
|
+
offers.get(doc)?.dispose();
|
|
57
|
+
const toast = doc.createElement(Toast.tagName);
|
|
58
|
+
const action = doc.createElement("button");
|
|
59
|
+
action.type = "button";
|
|
60
|
+
action.slot = "action";
|
|
61
|
+
action.textContent = "Undo";
|
|
62
|
+
const mac = /Mac|iPhone|iPad/.test(doc.defaultView?.navigator.platform ?? "");
|
|
63
|
+
const shortcut = mac ? "Command-Z" : "Control-Z";
|
|
64
|
+
action.setAttribute("aria-keyshortcuts", mac ? "Meta+Z" : "Control+Z");
|
|
65
|
+
toast.append(action);
|
|
66
|
+
let live = true;
|
|
67
|
+
const dispose = () => {
|
|
68
|
+
if (!live)
|
|
69
|
+
return;
|
|
70
|
+
live = false;
|
|
71
|
+
doc.removeEventListener("keydown", onKey);
|
|
72
|
+
toast.removeEventListener("open-changed", onOpen);
|
|
73
|
+
toast.hide();
|
|
74
|
+
toast.remove();
|
|
75
|
+
if (offers.get(doc) === offer)
|
|
76
|
+
offers.delete(doc);
|
|
77
|
+
};
|
|
78
|
+
const undo = () => {
|
|
79
|
+
if (!live)
|
|
80
|
+
return;
|
|
81
|
+
dispose();
|
|
82
|
+
restore();
|
|
83
|
+
options.onRestore?.();
|
|
84
|
+
announce("Restored", "polite", doc);
|
|
85
|
+
};
|
|
86
|
+
const onKey = (event) => {
|
|
87
|
+
if (event.defaultPrevented || event.isComposing || event.shiftKey || event.altKey || !(event.metaKey || event.ctrlKey) || event.key.toLowerCase() !== "z")
|
|
88
|
+
return;
|
|
89
|
+
const editing = event.composedPath().some(target => target instanceof HTMLElement && (target.matches("input, textarea, select, [role=textbox]") || target.isContentEditable));
|
|
90
|
+
if (editing)
|
|
91
|
+
return;
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
undo();
|
|
94
|
+
};
|
|
95
|
+
const onOpen = (event) => { if (!event.detail.open)
|
|
96
|
+
dispose(); };
|
|
97
|
+
const offer = { toast, undo, dispose };
|
|
98
|
+
offers.set(doc, offer);
|
|
99
|
+
action.addEventListener("click", undo);
|
|
100
|
+
toast.addEventListener("open-changed", onOpen);
|
|
101
|
+
doc.addEventListener("keydown", onKey);
|
|
102
|
+
(options.container ?? doc.body).append(toast);
|
|
103
|
+
// Toast owns the one persistent announcement, avoiding duplicate live messages.
|
|
104
|
+
toast.show(`${message}. Undo available with ${shortcut}.`, { duration: options.duration ?? 8000 });
|
|
105
|
+
return offer;
|
|
106
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unofficialbox/box-open-elements",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Box Open Elements: an open, framework-agnostic design system and web component library for Box-style experiences",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://unofficialbox.github.io/box-open-elements",
|
|
@@ -28,6 +28,14 @@
|
|
|
28
28
|
"main": "dist/index.js",
|
|
29
29
|
"types": "dist/index.d.ts",
|
|
30
30
|
"exports": {
|
|
31
|
+
"./patterns/undo": {
|
|
32
|
+
"types": "./dist/patterns/undo/index.d.ts",
|
|
33
|
+
"import": "./dist/patterns/undo/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./patterns/flow-builder": {
|
|
36
|
+
"types": "./dist/patterns/flow-builder/index.d.ts",
|
|
37
|
+
"import": "./dist/patterns/flow-builder/index.js"
|
|
38
|
+
},
|
|
31
39
|
".": {
|
|
32
40
|
"types": "./dist/index.d.ts",
|
|
33
41
|
"import": "./dist/index.js"
|
|
@@ -173,8 +181,9 @@
|
|
|
173
181
|
"dist"
|
|
174
182
|
],
|
|
175
183
|
"scripts": {
|
|
184
|
+
"bundles:check": "bun tools/adapters/bundle-check.ts",
|
|
176
185
|
"build": "bun run build:core && bun run build:adapters",
|
|
177
|
-
"build:core": "tsc -p tsconfig.json",
|
|
186
|
+
"build:core": "tsc -p tsconfig.json && cp src/foundations/icons/glyphs/package.json dist/foundations/icons/glyphs/package.json",
|
|
178
187
|
"build:adapters": "bun run adapters:version && bun run --cwd packages/react build && bun run --cwd packages/angular build && bun run --cwd packages/vue build && bun run --cwd packages/svelte build",
|
|
179
188
|
"build:watch": "tsc -p tsconfig.json --watch --preserveWatchOutput",
|
|
180
189
|
"prepublishOnly": "bun run build",
|