@llumi/design-system 1.0.1 → 2.1.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/LICENSE +51 -0
- package/NOTICE +66 -0
- package/README.md +15 -205
- package/adopt-global-styles-D9108lqB.js +15 -0
- package/base.css +2 -0
- package/base.md +59 -0
- package/bpmn.md +113 -0
- package/bpmn.mjs +5076 -0
- package/copy-button.md +128 -0
- package/copy-button.mjs +161 -0
- package/custom-elements.json +1135 -18
- package/download-button.md +106 -0
- package/download-button.mjs +177 -0
- package/highlighter.md +45 -0
- package/highlighter.mjs +403 -0
- package/icon-button-BwB11RGC.js +5 -0
- package/icons-BaUbjt-v.js +42 -0
- package/index-BEhA78nX.js +7733 -0
- package/llumi-element-BWRwgzW5.js +22 -0
- package/mermaid.md +58 -0
- package/mermaid.mjs +254 -0
- package/package.json +16 -50
- package/review.md +141 -0
- package/review.mjs +2044 -0
- package/slot-text-mSWBdWBc.js +51 -0
- package/theme.css +2 -0
- package/dist/review.cjs +0 -172
- package/dist/review.css +0 -98
- package/dist/review.js +0 -172
- package/dist/review.mjs +0 -1710
- package/dist/types/components/review/comment-dialog.element.d.ts +0 -29
- package/dist/types/components/review/custom-target.utils.d.ts +0 -16
- package/dist/types/components/review/default-editor.element.d.ts +0 -19
- package/dist/types/components/review/highlight-manager.d.ts +0 -21
- package/dist/types/components/review/index.d.ts +0 -8
- package/dist/types/components/review/overall-comment-dialog.element.d.ts +0 -22
- package/dist/types/components/review/review-bar.element.d.ts +0 -26
- package/dist/types/components/review/review.element.d.ts +0 -60
- package/dist/types/components/review/review.machine.d.ts +0 -234
- package/dist/types/components/review/review.persistence.d.ts +0 -16
- package/dist/types/components/review/review.type.d.ts +0 -37
- package/dist/types/components/review/selection-comment-icons.element.d.ts +0 -17
- package/dist/types/components/review/selection-range.utils.d.ts +0 -6
- package/dist/types/components/review/sort-comments.utils.d.ts +0 -6
- package/dist/types/index.d.ts +0 -1
- package/dist/types/shared/cn.d.ts +0 -2
- package/dist/types/shared/icons.d.ts +0 -7
- package/dist/types/shared/tailwind-element.d.ts +0 -4
package/copy-button.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# `<llumi-copy-button>`
|
|
2
|
+
|
|
3
|
+
Copy-to-clipboard icon button with animated success/error feedback.
|
|
4
|
+
|
|
5
|
+
## What it is
|
|
6
|
+
|
|
7
|
+
A minimal icon button that copies text to the clipboard and shows live state transitions:
|
|
8
|
+
|
|
9
|
+
| State | Visual |
|
|
10
|
+
|-------|--------|
|
|
11
|
+
| idle | copy icon |
|
|
12
|
+
| copying | spinning indicator (button disabled) |
|
|
13
|
+
| copied | green ✓ icon, resets after 1 s |
|
|
14
|
+
| error | red × icon, resets after 1 s |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
> **Requires the base theme.** This is a light-DOM element styled by the design-system stylesheet — load `@llumi/design-system/base.css` (or `base.css`) on the page, or the button renders unstyled.
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<!-- 1. Register the element (auto side-effect) -->
|
|
24
|
+
<script type="module">
|
|
25
|
+
import "@llumi/design-system/copy-button";
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<!-- 2. Drop the tag wherever you need it -->
|
|
29
|
+
<llumi-copy-button value="Text to copy"></llumi-copy-button>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or with named import:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import { LlumiCopyButton } from "@llumi/design-system/copy-button";
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Copy source precedence
|
|
41
|
+
|
|
42
|
+
The text that gets written to the clipboard is resolved from the first source that is available, in this order:
|
|
43
|
+
|
|
44
|
+
1. **`getValue` (JS function property)** — highest precedence. Assign a function:
|
|
45
|
+
```js
|
|
46
|
+
document.querySelector("llumi-copy-button").getValue = () => editor.getValue();
|
|
47
|
+
```
|
|
48
|
+
2. **`get-value` (attribute)** — a dotted path to a function on `globalThis`, resolved at click time via plain property traversal (no `eval`, no `new Function`). The component warns in the console if the path does not resolve to a function:
|
|
49
|
+
```html
|
|
50
|
+
<llumi-copy-button get-value="myApp.getSnippet"></llumi-copy-button>
|
|
51
|
+
```
|
|
52
|
+
```js
|
|
53
|
+
window.myApp = { getSnippet: () => editor.getValue() };
|
|
54
|
+
```
|
|
55
|
+
3. **`value` (string attribute)** — a plain, static string:
|
|
56
|
+
```html
|
|
57
|
+
<llumi-copy-button value="npm install @llumi/design-system"></llumi-copy-button>
|
|
58
|
+
```
|
|
59
|
+
4. **`""` (empty string)** — fallback when none of the above is set.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Attributes and properties
|
|
64
|
+
|
|
65
|
+
| Name | Type | Default | Notes |
|
|
66
|
+
|------|------|---------|-------|
|
|
67
|
+
| `value` | `string` attr + prop | `""` | Static text to copy. Lowest-precedence source. |
|
|
68
|
+
| `title` | `string` attr + prop | `"Copy to clipboard"` | Native tooltip; mirrored to `aria-label`. |
|
|
69
|
+
| `getValue` | `() => string` prop only | `undefined` | JS function property. No HTML attribute equivalent. Highest-precedence source. |
|
|
70
|
+
| `get-value` | `string` attr | — | Dotted path on `globalThis` resolving to a function. Resolved at click time. |
|
|
71
|
+
| `disabled` | — | — | Managed internally while copying; do not set manually. |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Events
|
|
76
|
+
|
|
77
|
+
Both events bubble and are composed.
|
|
78
|
+
|
|
79
|
+
### `llumi-copy`
|
|
80
|
+
|
|
81
|
+
Fires on a successful clipboard write.
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
element.addEventListener("llumi-copy", (e: CustomEvent<{ text: string }>) => {
|
|
85
|
+
console.log("Copied:", e.detail.text);
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### `llumi-copy-error`
|
|
90
|
+
|
|
91
|
+
Fires when `navigator.clipboard.writeText` rejects (e.g. permission denied in a non-HTTPS context or missing user gesture).
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
element.addEventListener("llumi-copy-error", (e: CustomEvent<{ error: unknown }>) => {
|
|
95
|
+
console.error("Copy failed:", e.detail.error);
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Styling
|
|
102
|
+
|
|
103
|
+
### Styling the button (light DOM)
|
|
104
|
+
|
|
105
|
+
The component renders in **light DOM**, so the inner `<button>` is a normal,
|
|
106
|
+
fully styleable element — no shadow piercing required:
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
llumi-copy-button button {
|
|
110
|
+
width: 3rem;
|
|
111
|
+
height: 3rem;
|
|
112
|
+
border-radius: 9999px;
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### CSS custom properties
|
|
117
|
+
|
|
118
|
+
Each token has a sensible `oklch` fallback, so the component is usable without a design-system theme.
|
|
119
|
+
|
|
120
|
+
| Token | Role | Fallback |
|
|
121
|
+
|-------|------|---------|
|
|
122
|
+
| `--llumi-color-success` | Border + icon colour in the copied state | `oklch(62.7% 0.194 149.214)` (green) |
|
|
123
|
+
| `--llumi-color-danger` | Border + icon colour in the error state | `oklch(57.7% 0.245 27.325)` (red) |
|
|
124
|
+
| `--llumi-color-surface` | Button background | `oklch(100% 0 0)` (white) |
|
|
125
|
+
| `--llumi-color-border` | Button border | `oklch(92% 0.004 286.32)` (light grey) |
|
|
126
|
+
| `--llumi-color-fg` | Icon colour (idle) | `oklch(21% 0.006 285.885)` (near-black) |
|
|
127
|
+
| `--llumi-color-ring` | Focus-visible outline | `oklch(55.8% 0.288 302.321)` (purple) |
|
|
128
|
+
| `--llumi-radius` | Button border-radius | `0.5rem` |
|
package/copy-button.mjs
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { html as d } from "https://cdn.jsdelivr.net/npm/lit@3.3.3";
|
|
2
|
+
import { property as u, customElement as h } from "https://cdn.jsdelivr.net/npm/lit@3.3.3/decorators.js";
|
|
3
|
+
import { i as s } from "./icons-BaUbjt-v.js";
|
|
4
|
+
import { L as b } from "./llumi-element-BWRwgzW5.js";
|
|
5
|
+
import { defineMachine as m } from "https://cdn.jsdelivr.net/npm/yay-machine@1.5.0";
|
|
6
|
+
/*! @llumi/design-system v2.1.0 | (c) 2026 pAIrprog SAS | license: https://cdn.jsdelivr.net/npm/@llumi/design-system@2.1.0/LICENSE | bundled third-party components under MIT, see NOTICE | @license */
|
|
7
|
+
const p = 1e3, f = m({
|
|
8
|
+
initialState: { name: "idle" },
|
|
9
|
+
states: {
|
|
10
|
+
idle: {
|
|
11
|
+
on: {
|
|
12
|
+
COPY: { to: "copying", data: ({ event: t }) => ({ text: t.text }) }
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
copying: {
|
|
16
|
+
onEnter: ({ state: t, send: e }) => {
|
|
17
|
+
navigator.clipboard.writeText(t.text).then(() => e({ type: "COPY_SUCCESS", text: t.text })).catch((o) => e({ type: "COPY_ERROR", error: o }));
|
|
18
|
+
},
|
|
19
|
+
on: {
|
|
20
|
+
COPY_SUCCESS: { to: "copied" },
|
|
21
|
+
COPY_ERROR: { to: "error" }
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
copied: {
|
|
25
|
+
onEnter: ({ send: t }) => {
|
|
26
|
+
const e = setTimeout(() => t({ type: "DONE" }), p);
|
|
27
|
+
return () => clearTimeout(e);
|
|
28
|
+
},
|
|
29
|
+
on: {
|
|
30
|
+
DONE: { to: "idle" },
|
|
31
|
+
COPY: { to: "copying", data: ({ event: t }) => ({ text: t.text }) }
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
error: {
|
|
35
|
+
onEnter: ({ send: t }) => {
|
|
36
|
+
const e = setTimeout(() => t({ type: "DONE" }), p);
|
|
37
|
+
return () => clearTimeout(e);
|
|
38
|
+
},
|
|
39
|
+
on: {
|
|
40
|
+
DONE: { to: "idle" },
|
|
41
|
+
COPY: { to: "copying", data: ({ event: t }) => ({ text: t.text }) }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
function y(t, e = globalThis) {
|
|
47
|
+
let o = e;
|
|
48
|
+
for (const r of t.split(".")) {
|
|
49
|
+
if (o == null) return;
|
|
50
|
+
o = o[r];
|
|
51
|
+
}
|
|
52
|
+
return o;
|
|
53
|
+
}
|
|
54
|
+
var C = Object.defineProperty, E = Object.getOwnPropertyDescriptor, c = (t, e, o, r) => {
|
|
55
|
+
for (var i = r > 1 ? void 0 : r ? E(e, o) : e, l = t.length - 1, a; l >= 0; l--)
|
|
56
|
+
(a = t[l]) && (i = (r ? a(e, o, i) : a(i)) || i);
|
|
57
|
+
return r && i && C(e, o, i), i;
|
|
58
|
+
};
|
|
59
|
+
function O(t) {
|
|
60
|
+
throw new Error(`Unexpected state: ${JSON.stringify(t)}`);
|
|
61
|
+
}
|
|
62
|
+
let n = class extends b {
|
|
63
|
+
constructor() {
|
|
64
|
+
super(...arguments), this.value = "", this.title = "Copy to clipboard";
|
|
65
|
+
}
|
|
66
|
+
/** Light DOM so the document-level base.css button style applies. */
|
|
67
|
+
createRenderRoot() {
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
connectedCallback() {
|
|
71
|
+
super.connectedCallback(), this.instance = f.newInstance().start(), this.unsubscribe = this.instance.subscribe(
|
|
72
|
+
({ state: t, event: e }) => this.onTransition(t, e)
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
disconnectedCallback() {
|
|
76
|
+
var t, e;
|
|
77
|
+
super.disconnectedCallback(), (t = this.unsubscribe) == null || t.call(this), this.unsubscribe = void 0, (e = this.instance) == null || e.stop(), this.instance = void 0;
|
|
78
|
+
}
|
|
79
|
+
onTransition(t, e) {
|
|
80
|
+
(e == null ? void 0 : e.type) === "COPY_SUCCESS" ? this.dispatchEvent(
|
|
81
|
+
new CustomEvent("llumi-copy", {
|
|
82
|
+
detail: { text: e.text },
|
|
83
|
+
bubbles: !0,
|
|
84
|
+
composed: !0
|
|
85
|
+
})
|
|
86
|
+
) : (e == null ? void 0 : e.type) === "COPY_ERROR" && this.dispatchEvent(
|
|
87
|
+
new CustomEvent("llumi-copy-error", {
|
|
88
|
+
detail: { error: e.error },
|
|
89
|
+
bubbles: !0,
|
|
90
|
+
composed: !0
|
|
91
|
+
})
|
|
92
|
+
), this.requestUpdate();
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Resolve the text to copy, by precedence:
|
|
96
|
+
* getValue() (function prop)
|
|
97
|
+
* → get-value (attribute: dotted path to a function on globalThis, resolved at click time)
|
|
98
|
+
* → value (string attr)
|
|
99
|
+
* → ""
|
|
100
|
+
*/
|
|
101
|
+
resolveText() {
|
|
102
|
+
if (typeof this.getValue == "function") return this.getValue();
|
|
103
|
+
const t = this.getAttribute("get-value");
|
|
104
|
+
if (t) {
|
|
105
|
+
const e = y(t);
|
|
106
|
+
if (typeof e == "function")
|
|
107
|
+
return String(e());
|
|
108
|
+
console.warn(
|
|
109
|
+
`<llumi-copy-button>: get-value="${t}" did not resolve to a function on globalThis`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
return this.value ?? "";
|
|
113
|
+
}
|
|
114
|
+
onClick() {
|
|
115
|
+
var t;
|
|
116
|
+
(t = this.instance) == null || t.send({ type: "COPY", text: this.resolveText() });
|
|
117
|
+
}
|
|
118
|
+
viewFor(t) {
|
|
119
|
+
switch (t) {
|
|
120
|
+
case "idle":
|
|
121
|
+
return { icon: s.copy, cls: "" };
|
|
122
|
+
case "copying":
|
|
123
|
+
return { icon: s.spinner, cls: "is-working" };
|
|
124
|
+
case "copied":
|
|
125
|
+
return { icon: s.check, cls: "is-done" };
|
|
126
|
+
case "error":
|
|
127
|
+
return { icon: s.x, cls: "is-error" };
|
|
128
|
+
default:
|
|
129
|
+
return O(t);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
render() {
|
|
133
|
+
var o;
|
|
134
|
+
const t = ((o = this.instance) == null ? void 0 : o.state.name) ?? "idle", e = this.viewFor(t);
|
|
135
|
+
return d`<button
|
|
136
|
+
type="button"
|
|
137
|
+
class=${e.cls}
|
|
138
|
+
title=${this.title}
|
|
139
|
+
aria-label=${this.title}
|
|
140
|
+
?disabled=${t === "copying"}
|
|
141
|
+
@click=${this.onClick}
|
|
142
|
+
>
|
|
143
|
+
<i>${e.icon}</i>
|
|
144
|
+
</button>`;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
c([
|
|
148
|
+
u()
|
|
149
|
+
], n.prototype, "value", 2);
|
|
150
|
+
c([
|
|
151
|
+
u()
|
|
152
|
+
], n.prototype, "title", 2);
|
|
153
|
+
c([
|
|
154
|
+
u({ attribute: !1 })
|
|
155
|
+
], n.prototype, "getValue", 2);
|
|
156
|
+
n = c([
|
|
157
|
+
h("llumi-copy-button")
|
|
158
|
+
], n);
|
|
159
|
+
export {
|
|
160
|
+
n as LlumiCopyButton
|
|
161
|
+
};
|