kanto-ds 1.2.0 → 1.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/README.md +21 -3
- package/dist/chunks/index-fzPIgxe2.js +74 -0
- package/dist/chunks/index-fzPIgxe2.js.map +1 -0
- package/dist/chunks/kt-element-mdd5cXZX.js +52 -0
- package/dist/chunks/kt-element-mdd5cXZX.js.map +1 -0
- package/dist/components/core/kt-avatar/kt-avatar.js +8 -7
- package/dist/components/core/kt-avatar/kt-avatar.js.map +1 -1
- package/dist/components/core/kt-badge/kt-badge.js +7 -6
- package/dist/components/core/kt-badge/kt-badge.js.map +1 -1
- package/dist/components/core/kt-button/kt-button.js +1 -1
- package/dist/components/core/kt-card/kt-card.js +1 -1
- package/dist/components/core/kt-code/kt-code.js +31 -30
- package/dist/components/core/kt-code/kt-code.js.map +1 -1
- package/dist/components/core/kt-icon/kt-icon.js +1 -1
- package/dist/components/core/kt-kbd/kt-kbd.js +1 -1
- package/dist/components/core/kt-split-button/kt-split-button.d.ts +2 -2
- package/dist/components/core/kt-split-button/kt-split-button.js +27 -26
- package/dist/components/core/kt-split-button/kt-split-button.js.map +1 -1
- package/dist/components/data/kt-chart/kt-chart.d.ts +2 -2
- package/dist/components/data/kt-chart/kt-chart.js +205 -204
- package/dist/components/data/kt-chart/kt-chart.js.map +1 -1
- package/dist/components/data/kt-meter/kt-meter.js +1 -1
- package/dist/components/data/kt-pagination/kt-pagination.d.ts +1 -1
- package/dist/components/data/kt-pagination/kt-pagination.js +29 -28
- package/dist/components/data/kt-pagination/kt-pagination.js.map +1 -1
- package/dist/components/data/kt-stat/kt-stat.js +1 -1
- package/dist/components/data/kt-table/kt-table.d.ts +2 -2
- package/dist/components/data/kt-table/kt-table.js +30 -29
- package/dist/components/data/kt-table/kt-table.js.map +1 -1
- package/dist/components/data/kt-timeline/kt-timeline.js +1 -1
- package/dist/components/feedback/kt-alert/kt-alert.js +17 -16
- package/dist/components/feedback/kt-alert/kt-alert.js.map +1 -1
- package/dist/components/feedback/kt-empty-state/kt-empty-state.js +1 -1
- package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js +1 -1
- package/dist/components/feedback/kt-skeleton/kt-skeleton.js +1 -1
- package/dist/components/feedback/kt-toast/kt-toast.js +25 -19
- package/dist/components/feedback/kt-toast/kt-toast.js.map +1 -1
- package/dist/components/feedback/kt-toast-container/kt-toast-container.js +1 -1
- package/dist/components/feedback/kt-tooltip/kt-tooltip.js +1 -1
- package/dist/components/forms/kt-drag-drop/kt-drag-drop.d.ts +2 -2
- package/dist/components/forms/kt-drag-drop/kt-drag-drop.js +60 -57
- package/dist/components/forms/kt-drag-drop/kt-drag-drop.js.map +1 -1
- package/dist/components/forms/kt-form/kt-form.js +1 -1
- package/dist/components/forms/kt-input/kt-input.js +56 -55
- package/dist/components/forms/kt-input/kt-input.js.map +1 -1
- package/dist/components/forms/kt-input-menu/kt-input-menu.d.ts +1 -1
- package/dist/components/forms/kt-input-menu/kt-input-menu.js +57 -56
- package/dist/components/forms/kt-input-menu/kt-input-menu.js.map +1 -1
- package/dist/components/forms/kt-label-input/kt-label-input.js +1 -1
- package/dist/components/forms/kt-select/kt-select.d.ts +2 -2
- package/dist/components/forms/kt-select/kt-select.js +62 -61
- package/dist/components/forms/kt-select/kt-select.js.map +1 -1
- package/dist/components/forms/kt-textarea/kt-textarea.js +9 -8
- package/dist/components/forms/kt-textarea/kt-textarea.js.map +1 -1
- package/dist/components/forms/kt-toggle/kt-toggle.js +1 -1
- package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.d.ts +1 -1
- package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js +6 -5
- package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js.map +1 -1
- package/dist/components/navigation/kt-header/kt-header.js +11 -10
- package/dist/components/navigation/kt-header/kt-header.js.map +1 -1
- package/dist/components/navigation/kt-page-header/kt-page-header.js +1 -1
- package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js +44 -43
- package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js.map +1 -1
- package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.d.ts +1 -1
- package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js +6 -5
- package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js.map +1 -1
- package/dist/components/navigation/kt-tabs/kt-tabs.js +1 -1
- package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js +1 -1
- package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js +1 -1
- package/dist/components/overlays/kt-collapsible/kt-collapsible.js +1 -1
- package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.d.ts +3 -3
- package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js +30 -27
- package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js.map +1 -1
- package/dist/components/overlays/kt-dropdown/kt-dropdown.d.ts +1 -1
- package/dist/components/overlays/kt-dropdown/kt-dropdown.js +8 -7
- package/dist/components/overlays/kt-dropdown/kt-dropdown.js.map +1 -1
- package/dist/components/overlays/kt-modal/kt-modal.js +5 -4
- package/dist/components/overlays/kt-modal/kt-modal.js.map +1 -1
- package/dist/components/overlays/kt-side-panel/kt-side-panel.d.ts +1 -1
- package/dist/components/overlays/kt-side-panel/kt-side-panel.js +24 -23
- package/dist/components/overlays/kt-side-panel/kt-side-panel.js.map +1 -1
- package/dist/custom-elements.json +76 -76
- package/dist/index.d.ts +1 -0
- package/dist/index.js +24 -19
- package/dist/index.js.map +1 -1
- package/dist/internal/kt-element.d.ts +6 -1
- package/dist/internal/strings.d.ts +93 -0
- package/dist/strings/index.d.ts +11 -0
- package/dist/strings/index.js +8 -0
- package/dist/strings/index.js.map +1 -0
- package/dist/tokens/base.css +53 -0
- package/dist/web-types.json +39 -39
- package/package.json +11 -3
- package/dist/chunks/kt-element-B_jjQDhg.js +0 -38
- package/dist/chunks/kt-element-B_jjQDhg.js.map +0 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ One implementation, every framework. The alternative — a React port, a Vue
|
|
|
38
38
|
port, an Angular library — is three codebases drifting apart.
|
|
39
39
|
|
|
40
40
|
The trade is real and worth naming: custom elements need JavaScript to upgrade,
|
|
41
|
-
so they
|
|
41
|
+
so during SSR they hold their place, hidden, until the bundle lands. In
|
|
42
42
|
return, a component is written once and a fix reaches every consumer at the same
|
|
43
43
|
time.
|
|
44
44
|
|
|
@@ -75,8 +75,26 @@ how an operation says it is still working when the number is not moving.
|
|
|
75
75
|
section titles. No emoji in product UI — the one exception is the flag in the
|
|
76
76
|
phone-input country picker, which is functional.
|
|
77
77
|
|
|
78
|
-
Every
|
|
79
|
-
|
|
78
|
+
Every string an element writes itself — empty states, button labels,
|
|
79
|
+
validation messages, and the accessible names only a screen reader hears — comes
|
|
80
|
+
from one registry. An application in another language replaces them once:
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
import { setStrings } from 'kanto-ds/strings';
|
|
84
|
+
|
|
85
|
+
setStrings({
|
|
86
|
+
clear: 'Effacer',
|
|
87
|
+
noData: 'Aucune donnée',
|
|
88
|
+
pageOf: (page, total) => `Page ${page} sur ${total}`,
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Anything left out stays in English, and switching at runtime re-renders every
|
|
93
|
+
element. Strings that carry a value are functions, so a translation owns the
|
|
94
|
+
word order. Where an element also takes a string as a property (`emptyText`,
|
|
95
|
+
`placeholder`, `confirmLabel`…), setting it still wins for that one element.
|
|
96
|
+
The full list is `KtStrings` in
|
|
97
|
+
[src/internal/strings.ts](src/internal/strings.ts).
|
|
80
98
|
|
|
81
99
|
Full details in **[src/tokens/README.md](src/tokens/README.md)**.
|
|
82
100
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const t = Object.freeze({
|
|
2
|
+
clear: "Clear",
|
|
3
|
+
close: "Close",
|
|
4
|
+
dismiss: "Dismiss",
|
|
5
|
+
copy: "Copy",
|
|
6
|
+
copied: "Copied",
|
|
7
|
+
copyCode: "Copy code",
|
|
8
|
+
timeRemaining: "Time remaining",
|
|
9
|
+
remove: (e) => e ? `Remove ${e}` : "Remove",
|
|
10
|
+
noOptions: "No options available",
|
|
11
|
+
noResults: "No results",
|
|
12
|
+
noActions: "No actions",
|
|
13
|
+
noData: "No data to display",
|
|
14
|
+
loading: "Loading…",
|
|
15
|
+
select: "Select",
|
|
16
|
+
openList: "Open list",
|
|
17
|
+
closeList: "Close list",
|
|
18
|
+
showPassword: "Show password",
|
|
19
|
+
hidePassword: "Hide password",
|
|
20
|
+
searchCountry: "Search country or dial code",
|
|
21
|
+
noCountry: "No country found",
|
|
22
|
+
countryCode: (e) => `Country code: ${e ?? "none"}`,
|
|
23
|
+
dragAndDrop: "Drag and drop or",
|
|
24
|
+
browseFiles: "browse your files",
|
|
25
|
+
recommendedSize: (e) => `Recommended image size: ${e}`,
|
|
26
|
+
selectedFiles: "Selected files",
|
|
27
|
+
required: "This field is required.",
|
|
28
|
+
selectOption: "Select an option.",
|
|
29
|
+
selectFile: "Select a file.",
|
|
30
|
+
openMenu: "Open menu",
|
|
31
|
+
closeMenu: "Close menu",
|
|
32
|
+
breadcrumb: "Breadcrumb",
|
|
33
|
+
secondaryNavigation: "Secondary navigation",
|
|
34
|
+
pagination: "Pagination",
|
|
35
|
+
previous: "Previous",
|
|
36
|
+
next: "Next",
|
|
37
|
+
pageOf: (e, o) => `Page ${e} / ${o}`,
|
|
38
|
+
moreActions: "More actions",
|
|
39
|
+
selectRow: "Select row",
|
|
40
|
+
selectAll: "Select all",
|
|
41
|
+
total: "Total",
|
|
42
|
+
chartSeries: "Series",
|
|
43
|
+
chartPoint: "Point",
|
|
44
|
+
chartSlice: "Slice",
|
|
45
|
+
chartShare: "Share",
|
|
46
|
+
confirmHeading: "Are you sure?",
|
|
47
|
+
confirm: "Confirm",
|
|
48
|
+
cancel: "Cancel",
|
|
49
|
+
details: "Details",
|
|
50
|
+
avatar: "Avatar"
|
|
51
|
+
});
|
|
52
|
+
let n = { ...t };
|
|
53
|
+
const s = /* @__PURE__ */ new Set();
|
|
54
|
+
function r() {
|
|
55
|
+
return n;
|
|
56
|
+
}
|
|
57
|
+
function i(e) {
|
|
58
|
+
n = { ...n, ...e };
|
|
59
|
+
for (const o of s) o();
|
|
60
|
+
}
|
|
61
|
+
function a() {
|
|
62
|
+
i(t);
|
|
63
|
+
}
|
|
64
|
+
function c(e) {
|
|
65
|
+
return s.add(e), () => s.delete(e);
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
i as a,
|
|
69
|
+
t as d,
|
|
70
|
+
c as o,
|
|
71
|
+
a as r,
|
|
72
|
+
r as s
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=index-fzPIgxe2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-fzPIgxe2.js","sources":["../../src/internal/strings.ts"],"sourcesContent":["/**\n * Every piece of copy the elements write themselves — empty states, button\n * labels, validation messages, and the accessible names a screen reader\n * announces but nobody sees.\n *\n * English by default. An application in another language replaces them once,\n * at start-up, and every element follows:\n *\n * import { setStrings } from 'kanto-ds/strings';\n *\n * setStrings({\n * clear: 'Effacer',\n * pageOf: (page, total) => `Page ${page} sur ${total}`,\n * });\n *\n * Anything left out keeps its English default. A string an element also takes\n * as a property — `emptyText`, `placeholder`, `confirmLabel` — still wins when\n * it is set, so one screen can say something different from the rest.\n *\n * Copy that carries a value is a function, not a template with placeholders:\n * the translation owns the word order, and \"Remove {name}\" does not survive\n * languages that put the object first.\n */\n\nexport interface KtStrings {\n // --- Shared actions ---\n /** Clear button in fields. */\n clear: string;\n /** Close button on toasts, alerts' dismiss button. */\n close: string;\n dismiss: string;\n /** Copy button on `kt-code`, and its state once copied. */\n copy: string;\n copied: string;\n copyCode: string;\n /** The countdown bar on a toast that closes itself. */\n timeRemaining: string;\n /** Remove button on a badge or a dropped file. */\n remove: (name: string) => string;\n\n // --- Empty and loading states ---\n noOptions: string;\n noResults: string;\n noActions: string;\n noData: string;\n loading: string;\n\n // --- Fields ---\n /** `kt-select` with nothing chosen. */\n select: string;\n openList: string;\n closeList: string;\n showPassword: string;\n hidePassword: string;\n searchCountry: string;\n noCountry: string;\n countryCode: (country: string | undefined) => string;\n dragAndDrop: string;\n browseFiles: string;\n recommendedSize: (size: string) => string;\n selectedFiles: string;\n\n // --- Validation messages, shown by the browser on submit ---\n required: string;\n selectOption: string;\n selectFile: string;\n\n // --- Navigation ---\n openMenu: string;\n closeMenu: string;\n breadcrumb: string;\n secondaryNavigation: string;\n pagination: string;\n previous: string;\n next: string;\n pageOf: (page: number, total: number) => string;\n moreActions: string;\n\n // --- Data ---\n selectRow: string;\n selectAll: string;\n total: string;\n /** Column headers of the data table every chart renders for assistive tech. */\n chartSeries: string;\n chartPoint: string;\n chartSlice: string;\n chartShare: string;\n\n // --- Overlays ---\n confirmHeading: string;\n confirm: string;\n cancel: string;\n details: string;\n\n // --- Identity ---\n avatar: string;\n}\n\nexport const defaultStrings: Readonly<KtStrings> = Object.freeze({\n clear: 'Clear',\n close: 'Close',\n dismiss: 'Dismiss',\n copy: 'Copy',\n copied: 'Copied',\n copyCode: 'Copy code',\n timeRemaining: 'Time remaining',\n remove: (name: string) => (name ? `Remove ${name}` : 'Remove'),\n\n noOptions: 'No options available',\n noResults: 'No results',\n noActions: 'No actions',\n noData: 'No data to display',\n loading: 'Loading…',\n\n select: 'Select',\n openList: 'Open list',\n closeList: 'Close list',\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n searchCountry: 'Search country or dial code',\n noCountry: 'No country found',\n countryCode: (country: string | undefined) => `Country code: ${country ?? 'none'}`,\n dragAndDrop: 'Drag and drop or',\n browseFiles: 'browse your files',\n recommendedSize: (size: string) => `Recommended image size: ${size}`,\n selectedFiles: 'Selected files',\n\n required: 'This field is required.',\n selectOption: 'Select an option.',\n selectFile: 'Select a file.',\n\n openMenu: 'Open menu',\n closeMenu: 'Close menu',\n breadcrumb: 'Breadcrumb',\n secondaryNavigation: 'Secondary navigation',\n pagination: 'Pagination',\n previous: 'Previous',\n next: 'Next',\n pageOf: (page: number, total: number) => `Page ${page} / ${total}`,\n moreActions: 'More actions',\n\n selectRow: 'Select row',\n selectAll: 'Select all',\n total: 'Total',\n chartSeries: 'Series',\n chartPoint: 'Point',\n chartSlice: 'Slice',\n chartShare: 'Share',\n\n confirmHeading: 'Are you sure?',\n confirm: 'Confirm',\n cancel: 'Cancel',\n details: 'Details',\n\n avatar: 'Avatar',\n});\n\nlet current: KtStrings = { ...defaultStrings };\nconst listeners = new Set<() => void>();\n\n/** The strings in effect. Elements read them at render time. */\nexport function strings(): Readonly<KtStrings> {\n return current;\n}\n\n/**\n * Replaces some or all of the strings, and re-renders every connected element\n * so the change shows at once — switching language at runtime works.\n */\nexport function setStrings(overrides: Partial<KtStrings>): void {\n current = { ...current, ...overrides };\n for (const listener of listeners) listener();\n}\n\n/** Back to the English defaults. */\nexport function resetStrings(): void {\n setStrings(defaultStrings);\n}\n\n/** Calls `listener` after every `setStrings`. Returns the unsubscribe function. */\nexport function onStringsChange(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n"],"names":["defaultStrings","name","country","size","page","total","current","listeners","strings","setStrings","overrides","listener","resetStrings","onStringsChange"],"mappings":"AAkGO,MAAMA,IAAsC,OAAO,OAAO;AAAA,EAC/D,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,eAAe;AAAA,EACf,QAAQ,CAACC,MAAkBA,IAAO,UAAUA,CAAI,KAAK;AAAA,EAErD,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,SAAS;AAAA,EAET,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA,EACf,WAAW;AAAA,EACX,aAAa,CAACC,MAAgC,iBAAiBA,KAAW,MAAM;AAAA,EAChF,aAAa;AAAA,EACb,aAAa;AAAA,EACb,iBAAiB,CAACC,MAAiB,2BAA2BA,CAAI;AAAA,EAClE,eAAe;AAAA,EAEf,UAAU;AAAA,EACV,cAAc;AAAA,EACd,YAAY;AAAA,EAEZ,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,qBAAqB;AAAA,EACrB,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ,CAACC,GAAcC,MAAkB,QAAQD,CAAI,MAAMC,CAAK;AAAA,EAChE,aAAa;AAAA,EAEb,WAAW;AAAA,EACX,WAAW;AAAA,EACX,OAAO;AAAA,EACP,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EAEZ,gBAAgB;AAAA,EAChB,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EAET,QAAQ;AACV,CAAC;AAED,IAAIC,IAAqB,EAAE,GAAGN,EAAA;AAC9B,MAAMO,wBAAgB,IAAA;AAGf,SAASC,IAA+B;AAC7C,SAAOF;AACT;AAMO,SAASG,EAAWC,GAAqC;AAC9D,EAAAJ,IAAU,EAAE,GAAGA,GAAS,GAAGI,EAAA;AAC3B,aAAWC,KAAYJ,EAAW,CAAAI,EAAA;AACpC;AAGO,SAASC,IAAqB;AACnC,EAAAH,EAAWT,CAAc;AAC3B;AAGO,SAASa,EAAgBF,GAAkC;AAChE,SAAAJ,EAAU,IAAII,CAAQ,GACf,MAAMJ,EAAU,OAAOI,CAAQ;AACxC;"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { LitElement as n, css as i } from "lit";
|
|
2
|
+
import { o } from "./index-fzPIgxe2.js";
|
|
3
|
+
const t = "kt-strings";
|
|
4
|
+
class c extends n {
|
|
5
|
+
static {
|
|
6
|
+
this.styles = i`
|
|
7
|
+
:host {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:host([hidden]) {
|
|
12
|
+
display: none !important;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
*,
|
|
16
|
+
*::before,
|
|
17
|
+
*::after {
|
|
18
|
+
box-sizing: inherit;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Read by assistive technology, never drawn. */
|
|
22
|
+
.visually-hidden {
|
|
23
|
+
position: absolute;
|
|
24
|
+
width: 1px;
|
|
25
|
+
height: 1px;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
clip-path: inset(50%);
|
|
28
|
+
white-space: nowrap;
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
32
|
+
connectedCallback() {
|
|
33
|
+
super.connectedCallback(), this.unsubscribeStrings = o(
|
|
34
|
+
() => this.requestUpdate(t, /* @__PURE__ */ Symbol("previous strings"))
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
disconnectedCallback() {
|
|
38
|
+
super.disconnectedCallback(), this.unsubscribeStrings?.(), this.unsubscribeStrings = void 0;
|
|
39
|
+
}
|
|
40
|
+
/** True when this update was triggered by `setStrings`. */
|
|
41
|
+
stringsChanged(s) {
|
|
42
|
+
return s.has(t);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function d(e, s) {
|
|
46
|
+
customElements.get(e) || customElements.define(e, s);
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
c as K,
|
|
50
|
+
d
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=kt-element-mdd5cXZX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kt-element-mdd5cXZX.js","sources":["../../src/internal/kt-element.ts"],"sourcesContent":["import { LitElement, css, type CSSResultGroup, type PropertyValues } from 'lit';\nimport { onStringsChange } from './strings.js';\n\n/**\n * The key a `setStrings` call marks in `changedProperties`, so an element can\n * recompute copy it caches outside `render()` — a validation message.\n */\nconst STRINGS_CHANGED = 'kt-strings';\n\n/**\n * Base class for every Kanto element.\n *\n * It exists for two reasons. First, `box-sizing: border-box` does not cross a\n * shadow boundary, so each root has to re-establish it. Second, `[hidden]`\n * loses to a `:host { display: flex }` rule inside the shadow root, and every\n * element in this system sets its own display — without the override here,\n * hiding a Kanto element from the outside silently does nothing.\n */\nexport class KtElement extends LitElement {\n static override styles: CSSResultGroup = css`\n :host {\n box-sizing: border-box;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n *,\n *::before,\n *::after {\n box-sizing: inherit;\n }\n\n /* Read by assistive technology, never drawn. */\n .visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n }\n `;\n\n private unsubscribeStrings: (() => void) | undefined;\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Copy comes from the strings registry at render time; follow it when an\n // application switches language.\n // A fresh old value, because Lit skips a named update whose value did not\n // change — and 'kt-strings' is not a property, so it is always undefined.\n this.unsubscribeStrings = onStringsChange(() =>\n this.requestUpdate(STRINGS_CHANGED, Symbol('previous strings')),\n );\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.unsubscribeStrings?.();\n this.unsubscribeStrings = undefined;\n }\n\n /** True when this update was triggered by `setStrings`. */\n protected stringsChanged(changed: PropertyValues): boolean {\n return changed.has(STRINGS_CHANGED);\n }\n}\n\n/**\n * Registers a custom element, tolerating a repeat call.\n *\n * A design system gets loaded twice more often than you would like — two\n * versions in one dependency tree, a dev-server hot reload, a micro-frontend\n * mounting a second copy. `customElements.define` throws on a duplicate tag\n * and would take the whole page down with it.\n */\nexport function defineElement(tag: string, ctor: CustomElementConstructor): void {\n if (customElements.get(tag)) return;\n customElements.define(tag, ctor);\n}\n"],"names":["STRINGS_CHANGED","KtElement","LitElement","css","onStringsChange","changed","defineElement","tag","ctor"],"mappings":";;AAOA,MAAMA,IAAkB;AAWjB,MAAMC,UAAkBC,EAAW;AAAA,EACxC,OAAA;AAAA,SAAgB,SAAyBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAAA;AAAA,EA4BhC,oBAA0B;AACjC,UAAM,kBAAA,GAKN,KAAK,qBAAqBC;AAAA,MAAgB,MACxC,KAAK,cAAcJ,GAAiB,uBAAO,kBAAkB,CAAC;AAAA,IAAA;AAAA,EAElE;AAAA,EAES,uBAA6B;AACpC,UAAM,qBAAA,GACN,KAAK,qBAAA,GACL,KAAK,qBAAqB;AAAA,EAC5B;AAAA;AAAA,EAGU,eAAeK,GAAkC;AACzD,WAAOA,EAAQ,IAAIL,CAAe;AAAA,EACpC;AACF;AAUO,SAASM,EAAcC,GAAaC,GAAsC;AAC/E,EAAI,eAAe,IAAID,CAAG,KAC1B,eAAe,OAAOA,GAAKC,CAAI;AACjC;"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { css as p, nothing as f, html as n } from "lit";
|
|
2
2
|
import { state as v, property as o } from "lit/decorators.js";
|
|
3
3
|
import { classMap as c } from "lit/directives/class-map.js";
|
|
4
|
-
import { K as d, d as g } from "../../../chunks/kt-element-
|
|
4
|
+
import { K as d, d as g } from "../../../chunks/kt-element-mdd5cXZX.js";
|
|
5
|
+
import { s as m } from "../../../chunks/index-fzPIgxe2.js";
|
|
5
6
|
import "../kt-icon/kt-icon.js";
|
|
6
|
-
var
|
|
7
|
+
var y = Object.defineProperty, s = (a, e, t, k) => {
|
|
7
8
|
for (var i = void 0, l = a.length - 1, h; l >= 0; l--)
|
|
8
9
|
(h = a[l]) && (i = h(e, t, i) || i);
|
|
9
|
-
return i &&
|
|
10
|
+
return i && y(e, t, i), i;
|
|
10
11
|
};
|
|
11
12
|
const u = Array.from({ length: 8 }, (a, e) => `var(--chart-series-${e + 1})`);
|
|
12
|
-
function
|
|
13
|
+
function b(a) {
|
|
13
14
|
const t = (a.includes("@") ? a.split("@")[0] ?? "" : a).split(/[\s._-]+/).filter(Boolean);
|
|
14
15
|
return t.length === 0 ? "" : t.length === 1 ? (t[0] ?? "").slice(0, 2).toUpperCase() : `${t[0][0]}${t[t.length - 1][0]}`.toUpperCase();
|
|
15
16
|
}
|
|
@@ -110,13 +111,13 @@ class r extends d {
|
|
|
110
111
|
return u[e % u.length];
|
|
111
112
|
}
|
|
112
113
|
render() {
|
|
113
|
-
const e =
|
|
114
|
+
const e = b(this.name), t = !!this.src && !this.failed;
|
|
114
115
|
return n`<span
|
|
115
116
|
part="base"
|
|
116
117
|
class=${c({ avatar: !0, "has-image": t, anonymous: !this.name })}
|
|
117
118
|
style=${t ? "" : `--kt-avatar-hue:${this.hue}`}
|
|
118
119
|
role="img"
|
|
119
|
-
aria-label=${this.name ||
|
|
120
|
+
aria-label=${this.name || m().avatar}
|
|
120
121
|
>
|
|
121
122
|
${t ? n`<img
|
|
122
123
|
part="image"
|
|
@@ -154,6 +155,6 @@ s([
|
|
|
154
155
|
g("kt-avatar", r);
|
|
155
156
|
export {
|
|
156
157
|
r as KtAvatar,
|
|
157
|
-
|
|
158
|
+
b as initialsOf
|
|
158
159
|
};
|
|
159
160
|
//# sourceMappingURL=kt-avatar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kt-avatar.js","sources":["../../../../src/components/core/kt-avatar/kt-avatar.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport '../kt-icon/kt-icon.js';\n\nexport type KtAvatarSize = 'small' | 'medium' | 'large';\nexport type KtAvatarStatus = 'online' | 'away' | 'busy' | 'offline';\n\n/**\n * Deterministic hue per name, so a person keeps their colour everywhere.\n *\n * From the chart palette, not the semantic one: status colours are reserved,\n * and a person filled with `--color-danger-base` reads as an error rather than\n * as a person. These eight are the same slots a chart uses, in the same fixed\n * order, so an avatar never impersonates a state.\n */\nconst HUES = Array.from({ length: 8 }, (_, i) => `var(--chart-series-${i + 1})`);\n\n/** \"Benjamin Canac\" → \"BC\", \"emma.davis@example.com\" → \"ED\". */\nexport function initialsOf(name: string): string {\n const cleaned = name.includes('@') ? (name.split('@')[0] ?? '') : name;\n const parts = cleaned.split(/[\\s._-]+/).filter(Boolean);\n\n if (parts.length === 0) return '';\n if (parts.length === 1) return (parts[0] ?? '').slice(0, 2).toUpperCase();\n return `${parts[0]![0]}${parts[parts.length - 1]![0]}`.toUpperCase();\n}\n\n/**\n * A person or an organisation, as a picture or as their initials.\n *\n * The fallback is not decoration: most rows in most products have no photo, so\n * the initials path is the one that renders. It picks a colour from the name,\n * which means the same person is the same colour on every screen and the eye\n * can use it.\n *\n * @element kt-avatar\n *\n * @csspart base - The avatar circle.\n * @csspart image - The `<img>`, when `src` is set and loads.\n *\n * @example\n * ```html\n * <kt-avatar name=\"Benjamin Canac\"></kt-avatar>\n * <kt-avatar name=\"Emma Davis\" src=\"/emma.jpg\" status=\"online\"></kt-avatar>\n * ```\n */\nexport class KtAvatar extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: inline-flex;\n --kt-avatar-size: 32px;\n }\n\n :host([size='small']) {\n --kt-avatar-size: 24px;\n }\n :host([size='large']) {\n --kt-avatar-size: 48px;\n }\n\n /* The identity hue is worn exactly the way every other tinted thing in\n Kanto wears one: the colour at 12% behind, the colour itself as the\n ink, and no border — the same pair as a secondary button, a danger\n button or a badge tone. A saturated fill with white initials is a\n different system's idea, and beside those it looks like one. */\n .avatar {\n position: relative;\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n width: var(--kt-avatar-size);\n height: var(--kt-avatar-size);\n overflow: hidden;\n /* The hue alone is too faint on its own 12% tint. Pulled towards the\n body text — lighter in dark, darker in light — it keeps its identity\n and clears 4.5:1 for all eight hues in both themes. */\n color: color-mix(in srgb, var(--kt-avatar-hue, var(--text-muted)) 45%, var(--text-body));\n font: 600 calc(var(--kt-avatar-size) * 0.36) / 1 var(--font-family-body);\n background: color-mix(in srgb, var(--kt-avatar-hue, transparent) 12%, transparent);\n border-radius: var(--radius-full);\n user-select: none;\n }\n\n /* No hue to tint with, and a photograph that fills the circle anyway. */\n .avatar.has-image,\n .avatar.anonymous {\n background: var(--surface-raised);\n }\n\n :host([square]) .avatar {\n border-radius: var(--border-radius);\n }\n\n img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n /* The dot sits outside the clipped circle, so it needs its own box. */\n .status {\n position: absolute;\n right: 0;\n bottom: 0;\n width: calc(var(--kt-avatar-size) * 0.28);\n height: calc(var(--kt-avatar-size) * 0.28);\n border: 2px solid var(--surface-page);\n border-radius: var(--radius-full);\n }\n\n .online {\n background: var(--color-success-base);\n }\n .away {\n background: var(--color-warning-base);\n }\n .busy {\n background: var(--color-danger-base);\n }\n .offline {\n background: var(--color-text-500);\n }\n `,\n ];\n\n @state()\n private failed = false;\n\n /** The person's name. Drives the initials, the colour and the label. */\n @property({ type: String })\n name = '';\n\n /** Photo. Falls back to initials if it is missing or fails to load. */\n @property({ type: String })\n src = '';\n\n @property({ type: String, reflect: true })\n size: KtAvatarSize = 'medium';\n\n /** Rounds to the card radius instead of a circle — for organisations. */\n @property({ type: Boolean, reflect: true })\n square = false;\n\n /** Presence dot. Omit for none. */\n @property({ type: String, reflect: true })\n status?: KtAvatarStatus;\n\n /** Overrides the colour picked from the name. */\n @property({ type: String })\n color = '';\n\n override willUpdate(changed: Map<string, unknown>): void {\n // A new source deserves a fresh attempt; without this a single failure\n // would stick for the element's lifetime.\n if (changed.has('src')) this.failed = false;\n }\n\n private get hue(): string {\n if (this.color) return this.color;\n\n let sum = 0;\n for (const char of this.name) sum += char.charCodeAt(0);\n return HUES[sum % HUES.length]!;\n }\n\n override render(): TemplateResult {\n const initials = initialsOf(this.name);\n const showImage = Boolean(this.src) && !this.failed;\n\n return html`<span\n part=\"base\"\n class=${classMap({ avatar: true, 'has-image': showImage, anonymous: !this.name })}\n style=${showImage ? '' : `--kt-avatar-hue:${this.hue}`}\n role=\"img\"\n aria-label=${this.name ||
|
|
1
|
+
{"version":3,"file":"kt-avatar.js","sources":["../../../../src/components/core/kt-avatar/kt-avatar.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { strings } from '#internal/strings';\nimport '../kt-icon/kt-icon.js';\n\nexport type KtAvatarSize = 'small' | 'medium' | 'large';\nexport type KtAvatarStatus = 'online' | 'away' | 'busy' | 'offline';\n\n/**\n * Deterministic hue per name, so a person keeps their colour everywhere.\n *\n * From the chart palette, not the semantic one: status colours are reserved,\n * and a person filled with `--color-danger-base` reads as an error rather than\n * as a person. These eight are the same slots a chart uses, in the same fixed\n * order, so an avatar never impersonates a state.\n */\nconst HUES = Array.from({ length: 8 }, (_, i) => `var(--chart-series-${i + 1})`);\n\n/** \"Benjamin Canac\" → \"BC\", \"emma.davis@example.com\" → \"ED\". */\nexport function initialsOf(name: string): string {\n const cleaned = name.includes('@') ? (name.split('@')[0] ?? '') : name;\n const parts = cleaned.split(/[\\s._-]+/).filter(Boolean);\n\n if (parts.length === 0) return '';\n if (parts.length === 1) return (parts[0] ?? '').slice(0, 2).toUpperCase();\n return `${parts[0]![0]}${parts[parts.length - 1]![0]}`.toUpperCase();\n}\n\n/**\n * A person or an organisation, as a picture or as their initials.\n *\n * The fallback is not decoration: most rows in most products have no photo, so\n * the initials path is the one that renders. It picks a colour from the name,\n * which means the same person is the same colour on every screen and the eye\n * can use it.\n *\n * @element kt-avatar\n *\n * @csspart base - The avatar circle.\n * @csspart image - The `<img>`, when `src` is set and loads.\n *\n * @example\n * ```html\n * <kt-avatar name=\"Benjamin Canac\"></kt-avatar>\n * <kt-avatar name=\"Emma Davis\" src=\"/emma.jpg\" status=\"online\"></kt-avatar>\n * ```\n */\nexport class KtAvatar extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: inline-flex;\n --kt-avatar-size: 32px;\n }\n\n :host([size='small']) {\n --kt-avatar-size: 24px;\n }\n :host([size='large']) {\n --kt-avatar-size: 48px;\n }\n\n /* The identity hue is worn exactly the way every other tinted thing in\n Kanto wears one: the colour at 12% behind, the colour itself as the\n ink, and no border — the same pair as a secondary button, a danger\n button or a badge tone. A saturated fill with white initials is a\n different system's idea, and beside those it looks like one. */\n .avatar {\n position: relative;\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n width: var(--kt-avatar-size);\n height: var(--kt-avatar-size);\n overflow: hidden;\n /* The hue alone is too faint on its own 12% tint. Pulled towards the\n body text — lighter in dark, darker in light — it keeps its identity\n and clears 4.5:1 for all eight hues in both themes. */\n color: color-mix(in srgb, var(--kt-avatar-hue, var(--text-muted)) 45%, var(--text-body));\n font: 600 calc(var(--kt-avatar-size) * 0.36) / 1 var(--font-family-body);\n background: color-mix(in srgb, var(--kt-avatar-hue, transparent) 12%, transparent);\n border-radius: var(--radius-full);\n user-select: none;\n }\n\n /* No hue to tint with, and a photograph that fills the circle anyway. */\n .avatar.has-image,\n .avatar.anonymous {\n background: var(--surface-raised);\n }\n\n :host([square]) .avatar {\n border-radius: var(--border-radius);\n }\n\n img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n /* The dot sits outside the clipped circle, so it needs its own box. */\n .status {\n position: absolute;\n right: 0;\n bottom: 0;\n width: calc(var(--kt-avatar-size) * 0.28);\n height: calc(var(--kt-avatar-size) * 0.28);\n border: 2px solid var(--surface-page);\n border-radius: var(--radius-full);\n }\n\n .online {\n background: var(--color-success-base);\n }\n .away {\n background: var(--color-warning-base);\n }\n .busy {\n background: var(--color-danger-base);\n }\n .offline {\n background: var(--color-text-500);\n }\n `,\n ];\n\n @state()\n private failed = false;\n\n /** The person's name. Drives the initials, the colour and the label. */\n @property({ type: String })\n name = '';\n\n /** Photo. Falls back to initials if it is missing or fails to load. */\n @property({ type: String })\n src = '';\n\n @property({ type: String, reflect: true })\n size: KtAvatarSize = 'medium';\n\n /** Rounds to the card radius instead of a circle — for organisations. */\n @property({ type: Boolean, reflect: true })\n square = false;\n\n /** Presence dot. Omit for none. */\n @property({ type: String, reflect: true })\n status?: KtAvatarStatus;\n\n /** Overrides the colour picked from the name. */\n @property({ type: String })\n color = '';\n\n override willUpdate(changed: Map<string, unknown>): void {\n // A new source deserves a fresh attempt; without this a single failure\n // would stick for the element's lifetime.\n if (changed.has('src')) this.failed = false;\n }\n\n private get hue(): string {\n if (this.color) return this.color;\n\n let sum = 0;\n for (const char of this.name) sum += char.charCodeAt(0);\n return HUES[sum % HUES.length]!;\n }\n\n override render(): TemplateResult {\n const initials = initialsOf(this.name);\n const showImage = Boolean(this.src) && !this.failed;\n\n return html`<span\n part=\"base\"\n class=${classMap({ avatar: true, 'has-image': showImage, anonymous: !this.name })}\n style=${showImage ? '' : `--kt-avatar-hue:${this.hue}`}\n role=\"img\"\n aria-label=${this.name || strings().avatar}\n >\n ${\n showImage\n ? html`<img\n part=\"image\"\n src=${this.src}\n alt=\"\"\n @error=${() => {\n this.failed = true;\n }}\n />`\n : initials || html`<kt-icon name=\"user\" size=\"16\"></kt-icon>`\n }\n ${\n this.status\n ? html`<span class=${classMap({ status: true, [this.status]: true })}></span>`\n : nothing\n }\n </span>`;\n }\n}\n\ndefineElement('kt-avatar', KtAvatar);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-avatar': KtAvatar;\n }\n}\n"],"names":["HUES","_","i","initialsOf","name","parts","KtAvatar","KtElement","css","changed","sum","char","initials","showImage","html","classMap","strings","nothing","__decorateClass","state","property","defineElement"],"mappings":"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"}
|
|
@@ -2,13 +2,14 @@ import { css as h, nothing as n, html as l } from "lit";
|
|
|
2
2
|
import { property as e } from "lit/decorators.js";
|
|
3
3
|
import { classMap as b } from "lit/directives/class-map.js";
|
|
4
4
|
import { styleMap as m } from "lit/directives/style-map.js";
|
|
5
|
-
import { K as p, d as v } from "../../../chunks/kt-element-
|
|
5
|
+
import { K as p, d as v } from "../../../chunks/kt-element-mdd5cXZX.js";
|
|
6
6
|
import { e as u } from "../../../chunks/events-Bjl5Zmmq.js";
|
|
7
|
+
import { s as g } from "../../../chunks/index-fzPIgxe2.js";
|
|
7
8
|
import "../kt-icon/kt-icon.js";
|
|
8
|
-
var
|
|
9
|
-
for (var a = void 0,
|
|
10
|
-
(d = c
|
|
11
|
-
return a &&
|
|
9
|
+
var f = Object.defineProperty, t = (s, r, i, y) => {
|
|
10
|
+
for (var a = void 0, c = s.length - 1, d; c >= 0; c--)
|
|
11
|
+
(d = s[c]) && (a = d(r, i, a) || a);
|
|
12
|
+
return a && f(r, i, a), a;
|
|
12
13
|
};
|
|
13
14
|
class o extends p {
|
|
14
15
|
constructor() {
|
|
@@ -209,7 +210,7 @@ class o extends p {
|
|
|
209
210
|
part="remove"
|
|
210
211
|
type="button"
|
|
211
212
|
class="remove"
|
|
212
|
-
aria-label=${
|
|
213
|
+
aria-label=${g().remove(this.display || this.textContent?.trim() || "")}
|
|
213
214
|
@click=${this.onRemove}
|
|
214
215
|
>
|
|
215
216
|
<kt-icon name="x" size="12"></kt-icon>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kt-badge.js","sources":["../../../../src/components/core/kt-badge/kt-badge.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport '../kt-icon/kt-icon.js';\n\nexport type KtBadgeVariant = 'tag' | 'code' | 'category' | 'count';\nexport type KtBadgeTone = 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info';\nexport type KtBadgeSize = 'small' | 'medium';\n\n/**\n * A compact label: a pill `tag`, a monospaced `code` token, a `category`\n * tinted with a colour of your choosing, or a `count`.\n *\n * Two independent axes, because they answer different questions. `variant` is\n * the **shape** — what kind of thing this is. `tone` is the **colour** — what\n * it means. A tag can be neutral or dangerous; so can a count. Folding them\n * into one list would give you nine variants and no way to say \"a tag, but\n * this one is a warning\".\n *\n * `count` is the exception that carries no border, because a number pinned to\n * a nav item is not a label with an outline — it is a mark on the thing it\n * counts.\n *\n * @element kt-badge\n *\n * @slot - The text. Falls back to the `label` attribute.\n *\n * @csspart base - The container.\n * @csspart remove - The remove button, when `removable`.\n *\n * @cssproperty --kt-badge-color - Category hue. The fill is this colour at 20%.\n *\n * @fires kt-badge-click - A `clickable` badge was activated. Cancelable.\n * @fires kt-remove - The remove button was pressed. Cancelable: cancel it and\n * remove the badge yourself once the server agrees.\n *\n * @example\n * ```html\n * <kt-badge>Design systems</kt-badge>\n * <kt-badge tone=\"success\">Active</kt-badge>\n * <kt-badge variant=\"code\">--surface-card</kt-badge>\n * <kt-badge variant=\"category\" color=\"#3987e5\">Infrastructure</kt-badge>\n * <kt-badge variant=\"count\" tone=\"danger\" max=\"99\">128</kt-badge>\n * <kt-badge icon=\"user\" removable>Assigned to me</kt-badge>\n * ```\n */\nexport class KtBadge extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n --kt-badge-color: var(--color-primary-text);\n }\n\n .badge {\n display: inline-flex;\n align-items: center;\n gap: var(--gap-element);\n width: fit-content;\n margin: 0;\n padding: var(--padding-chip);\n color: var(--text-body);\n font: var(--font-normal-regular);\n background-color: var(--color-dark-20);\n border: var(--border-width) solid var(--color-text-600);\n border-radius: var(--radius-input);\n white-space: normal;\n }\n\n .small {\n padding: 2px 8px;\n font: var(--font-normal-small);\n }\n\n /* === TAG === */\n .tag {\n border-radius: var(--radius-pill);\n }\n\n /* === CODE ===\n Uses the semantic code surface rather than a ramp step: --color-dark-8\n is the darkest surface in the dark theme and pure white in the light\n one, which made this badge white-on-white. */\n .code {\n color: var(--text-code);\n font: var(--font-code-regular);\n background-color: var(--surface-code);\n border-color: var(--border-code);\n }\n\n /* === CATEGORY ===\n color-mix keeps the 20% fill honest for any colour notation the host\n hands us; concatenating a \"33\" onto a hex string produces garbage\n for rgb() and named colours. */\n .category {\n color: var(--kt-badge-color);\n background-color: color-mix(in srgb, var(--kt-badge-color) 20%, transparent);\n border-color: var(--kt-badge-color);\n }\n\n /* === COUNT ===\n No border: a number pinned to a nav item is a mark on the thing it\n counts, not a label with an outline of its own. */\n .count {\n min-width: 20px;\n padding: 2px 6px;\n justify-content: center;\n color: var(--text-muted);\n font: var(--font-normal-small);\n font-variant-numeric: tabular-nums;\n line-height: 1.4;\n white-space: nowrap;\n background: var(--surface-raised);\n border: none;\n border-radius: var(--radius-pill);\n }\n\n /* === TONES ===\n The system's tinted pair everywhere: the colour at 12% behind, the\n colour itself as the ink. The border follows on the bordered shapes\n and is simply absent on the count shape. */\n .primary {\n color: var(--color-primary-text);\n background-color: var(--color-primary-soft);\n border-color: var(--color-primary-base);\n }\n .success {\n color: var(--color-success-text);\n background-color: var(--color-success-soft);\n border-color: var(--color-success-base);\n }\n .warning {\n color: var(--color-warning-text);\n background-color: var(--color-warning-soft);\n border-color: var(--color-warning-base);\n }\n .danger {\n color: var(--color-danger-text);\n background-color: var(--color-danger-soft);\n border-color: var(--color-danger-base);\n }\n .info {\n color: var(--color-info-text);\n background-color: var(--color-info-soft);\n border-color: var(--color-info-base);\n }\n\n .count.primary,\n .count.success,\n .count.warning,\n .count.danger,\n .count.info {\n border: none;\n }\n\n /* === CLICKABLE === */\n .clickable {\n cursor: pointer;\n }\n .clickable:hover {\n outline: var(--outline-width) solid var(--text-muted);\n }\n .clickable:active {\n color: var(--color-white);\n background-color: var(--color-primary-base);\n border-color: transparent;\n }\n .clickable:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 2px;\n }\n\n .remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-right: -4px;\n padding: 0;\n color: inherit;\n background: none;\n border: none;\n border-radius: var(--radius-pill);\n cursor: pointer;\n opacity: 0.65;\n }\n\n .remove:hover {\n opacity: 1;\n }\n\n .remove:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n kt-icon {\n flex: none;\n }\n `,\n ];\n\n /** The shape: what kind of thing this is. */\n @property({ type: String, reflect: true })\n variant: KtBadgeVariant = 'tag';\n\n /** The colour: what it means. Independent of `variant`. */\n @property({ type: String, reflect: true })\n tone: KtBadgeTone = 'neutral';\n\n @property({ type: String, reflect: true })\n size: KtBadgeSize = 'medium';\n\n /** Badge text. The default slot wins when both are present. */\n @property({ type: String })\n label = '';\n\n /** Category hue: any CSS colour. The fill is this colour at 20%. */\n @property({ type: String })\n color = '';\n\n /** Lucide icon name, before the text. */\n @property({ type: String })\n icon = '';\n\n @property({ type: Boolean, reflect: true })\n clickable = false;\n\n /** Adds a remove button. Fires a cancelable `kt-remove`. */\n @property({ type: Boolean, reflect: true })\n removable = false;\n\n /**\n * Caps a numeric label: `max=\"99\"` shows `99+`.\n * Ignored when the content is not a number.\n */\n @property({ type: Number })\n max?: number;\n\n /** Shorthand for `tone=\"danger\"`, kept from the field components. */\n @property({ type: Boolean, reflect: true })\n error = false;\n\n private get display(): string {\n const raw = this.label || (this.textContent ?? '').trim();\n if (this.max === undefined) return raw;\n\n const n = Number(raw);\n return Number.isFinite(n) && n > this.max ? `${this.max}+` : raw;\n }\n\n private activate(): void {\n if (this.clickable) emit(this, 'kt-badge-click');\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n if (!this.clickable) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n this.activate();\n }\n\n private onRemove(event: Event): void {\n // Otherwise a removable clickable badge reports both at once.\n event.stopPropagation();\n emit(this, 'kt-remove');\n }\n\n override render(): TemplateResult {\n const tone = this.error ? 'danger' : this.tone;\n\n return html`<span\n part=\"base\"\n class=${classMap({\n badge: true,\n [this.variant]: true,\n [tone]: tone !== 'neutral',\n small: this.size === 'small',\n clickable: this.clickable,\n })}\n style=${styleMap(this.color ? { '--kt-badge-color': this.color } : {})}\n role=${this.clickable ? 'button' : nothing}\n tabindex=${this.clickable ? 0 : nothing}\n @click=${this.activate}\n @keydown=${this.onKeyDown}\n >\n ${this.icon ? html`<kt-icon name=${this.icon} size=\"14\"></kt-icon>` : nothing}\n ${this.max === undefined ? html`<slot>${this.label}</slot>` : this.display}\n ${\n this.removable\n ? html`<button\n part=\"remove\"\n type=\"button\"\n class=\"remove\"\n aria-label=${`Remove ${this.display || 'this'}`}\n @click=${this.onRemove}\n >\n <kt-icon name=\"x\" size=\"12\"></kt-icon>\n </button>`\n : nothing\n }\n </span>`;\n }\n}\n\ndefineElement('kt-badge', KtBadge);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-badge': KtBadge;\n }\n}\n"],"names":["KtBadge","KtElement","css","raw","n","emit","event","tone","html","classMap","styleMap","nothing","__decorateClass","property","defineElement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"kt-badge.js","sources":["../../../../src/components/core/kt-badge/kt-badge.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport { strings } from '#internal/strings';\nimport '../kt-icon/kt-icon.js';\n\nexport type KtBadgeVariant = 'tag' | 'code' | 'category' | 'count';\nexport type KtBadgeTone = 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info';\nexport type KtBadgeSize = 'small' | 'medium';\n\n/**\n * A compact label: a pill `tag`, a monospaced `code` token, a `category`\n * tinted with a colour of your choosing, or a `count`.\n *\n * Two independent axes, because they answer different questions. `variant` is\n * the **shape** — what kind of thing this is. `tone` is the **colour** — what\n * it means. A tag can be neutral or dangerous; so can a count. Folding them\n * into one list would give you nine variants and no way to say \"a tag, but\n * this one is a warning\".\n *\n * `count` is the exception that carries no border, because a number pinned to\n * a nav item is not a label with an outline — it is a mark on the thing it\n * counts.\n *\n * @element kt-badge\n *\n * @slot - The text. Falls back to the `label` attribute.\n *\n * @csspart base - The container.\n * @csspart remove - The remove button, when `removable`.\n *\n * @cssproperty --kt-badge-color - Category hue. The fill is this colour at 20%.\n *\n * @fires kt-badge-click - A `clickable` badge was activated. Cancelable.\n * @fires kt-remove - The remove button was pressed. Cancelable: cancel it and\n * remove the badge yourself once the server agrees.\n *\n * @example\n * ```html\n * <kt-badge>Design systems</kt-badge>\n * <kt-badge tone=\"success\">Active</kt-badge>\n * <kt-badge variant=\"code\">--surface-card</kt-badge>\n * <kt-badge variant=\"category\" color=\"#3987e5\">Infrastructure</kt-badge>\n * <kt-badge variant=\"count\" tone=\"danger\" max=\"99\">128</kt-badge>\n * <kt-badge icon=\"user\" removable>Assigned to me</kt-badge>\n * ```\n */\nexport class KtBadge extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n --kt-badge-color: var(--color-primary-text);\n }\n\n .badge {\n display: inline-flex;\n align-items: center;\n gap: var(--gap-element);\n width: fit-content;\n margin: 0;\n padding: var(--padding-chip);\n color: var(--text-body);\n font: var(--font-normal-regular);\n background-color: var(--color-dark-20);\n border: var(--border-width) solid var(--color-text-600);\n border-radius: var(--radius-input);\n white-space: normal;\n }\n\n .small {\n padding: 2px 8px;\n font: var(--font-normal-small);\n }\n\n /* === TAG === */\n .tag {\n border-radius: var(--radius-pill);\n }\n\n /* === CODE ===\n Uses the semantic code surface rather than a ramp step: --color-dark-8\n is the darkest surface in the dark theme and pure white in the light\n one, which made this badge white-on-white. */\n .code {\n color: var(--text-code);\n font: var(--font-code-regular);\n background-color: var(--surface-code);\n border-color: var(--border-code);\n }\n\n /* === CATEGORY ===\n color-mix keeps the 20% fill honest for any colour notation the host\n hands us; concatenating a \"33\" onto a hex string produces garbage\n for rgb() and named colours. */\n .category {\n color: var(--kt-badge-color);\n background-color: color-mix(in srgb, var(--kt-badge-color) 20%, transparent);\n border-color: var(--kt-badge-color);\n }\n\n /* === COUNT ===\n No border: a number pinned to a nav item is a mark on the thing it\n counts, not a label with an outline of its own. */\n .count {\n min-width: 20px;\n padding: 2px 6px;\n justify-content: center;\n color: var(--text-muted);\n font: var(--font-normal-small);\n font-variant-numeric: tabular-nums;\n line-height: 1.4;\n white-space: nowrap;\n background: var(--surface-raised);\n border: none;\n border-radius: var(--radius-pill);\n }\n\n /* === TONES ===\n The system's tinted pair everywhere: the colour at 12% behind, the\n colour itself as the ink. The border follows on the bordered shapes\n and is simply absent on the count shape. */\n .primary {\n color: var(--color-primary-text);\n background-color: var(--color-primary-soft);\n border-color: var(--color-primary-base);\n }\n .success {\n color: var(--color-success-text);\n background-color: var(--color-success-soft);\n border-color: var(--color-success-base);\n }\n .warning {\n color: var(--color-warning-text);\n background-color: var(--color-warning-soft);\n border-color: var(--color-warning-base);\n }\n .danger {\n color: var(--color-danger-text);\n background-color: var(--color-danger-soft);\n border-color: var(--color-danger-base);\n }\n .info {\n color: var(--color-info-text);\n background-color: var(--color-info-soft);\n border-color: var(--color-info-base);\n }\n\n .count.primary,\n .count.success,\n .count.warning,\n .count.danger,\n .count.info {\n border: none;\n }\n\n /* === CLICKABLE === */\n .clickable {\n cursor: pointer;\n }\n .clickable:hover {\n outline: var(--outline-width) solid var(--text-muted);\n }\n .clickable:active {\n color: var(--color-white);\n background-color: var(--color-primary-base);\n border-color: transparent;\n }\n .clickable:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 2px;\n }\n\n .remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-right: -4px;\n padding: 0;\n color: inherit;\n background: none;\n border: none;\n border-radius: var(--radius-pill);\n cursor: pointer;\n opacity: 0.65;\n }\n\n .remove:hover {\n opacity: 1;\n }\n\n .remove:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n kt-icon {\n flex: none;\n }\n `,\n ];\n\n /** The shape: what kind of thing this is. */\n @property({ type: String, reflect: true })\n variant: KtBadgeVariant = 'tag';\n\n /** The colour: what it means. Independent of `variant`. */\n @property({ type: String, reflect: true })\n tone: KtBadgeTone = 'neutral';\n\n @property({ type: String, reflect: true })\n size: KtBadgeSize = 'medium';\n\n /** Badge text. The default slot wins when both are present. */\n @property({ type: String })\n label = '';\n\n /** Category hue: any CSS colour. The fill is this colour at 20%. */\n @property({ type: String })\n color = '';\n\n /** Lucide icon name, before the text. */\n @property({ type: String })\n icon = '';\n\n @property({ type: Boolean, reflect: true })\n clickable = false;\n\n /** Adds a remove button. Fires a cancelable `kt-remove`. */\n @property({ type: Boolean, reflect: true })\n removable = false;\n\n /**\n * Caps a numeric label: `max=\"99\"` shows `99+`.\n * Ignored when the content is not a number.\n */\n @property({ type: Number })\n max?: number;\n\n /** Shorthand for `tone=\"danger\"`, kept from the field components. */\n @property({ type: Boolean, reflect: true })\n error = false;\n\n private get display(): string {\n const raw = this.label || (this.textContent ?? '').trim();\n if (this.max === undefined) return raw;\n\n const n = Number(raw);\n return Number.isFinite(n) && n > this.max ? `${this.max}+` : raw;\n }\n\n private activate(): void {\n if (this.clickable) emit(this, 'kt-badge-click');\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n if (!this.clickable) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n this.activate();\n }\n\n private onRemove(event: Event): void {\n // Otherwise a removable clickable badge reports both at once.\n event.stopPropagation();\n emit(this, 'kt-remove');\n }\n\n override render(): TemplateResult {\n const tone = this.error ? 'danger' : this.tone;\n\n return html`<span\n part=\"base\"\n class=${classMap({\n badge: true,\n [this.variant]: true,\n [tone]: tone !== 'neutral',\n small: this.size === 'small',\n clickable: this.clickable,\n })}\n style=${styleMap(this.color ? { '--kt-badge-color': this.color } : {})}\n role=${this.clickable ? 'button' : nothing}\n tabindex=${this.clickable ? 0 : nothing}\n @click=${this.activate}\n @keydown=${this.onKeyDown}\n >\n ${this.icon ? html`<kt-icon name=${this.icon} size=\"14\"></kt-icon>` : nothing}\n ${this.max === undefined ? html`<slot>${this.label}</slot>` : this.display}\n ${\n this.removable\n ? html`<button\n part=\"remove\"\n type=\"button\"\n class=\"remove\"\n aria-label=${strings().remove(this.display || this.textContent?.trim() || '')}\n @click=${this.onRemove}\n >\n <kt-icon name=\"x\" size=\"12\"></kt-icon>\n </button>`\n : nothing\n }\n </span>`;\n }\n}\n\ndefineElement('kt-badge', KtBadge);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-badge': KtBadge;\n }\n}\n"],"names":["KtBadge","KtElement","css","raw","n","emit","event","tone","html","classMap","styleMap","nothing","strings","__decorateClass","property","defineElement"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { css as h, html as d, nothing as i } from "lit";
|
|
2
2
|
import { property as e } from "lit/decorators.js";
|
|
3
3
|
import { classMap as p } from "lit/directives/class-map.js";
|
|
4
|
-
import { K as u, d as v } from "../../../chunks/kt-element-
|
|
4
|
+
import { K as u, d as v } from "../../../chunks/kt-element-mdd5cXZX.js";
|
|
5
5
|
import "../kt-icon/kt-icon.js";
|
|
6
6
|
var g = Object.defineProperty, a = (l, t, o, y) => {
|
|
7
7
|
for (var n = void 0, c = l.length - 1, s; c >= 0; c--)
|
|
@@ -2,7 +2,7 @@ import { css as f, nothing as r, html as d } from "lit";
|
|
|
2
2
|
import { state as g, property as a } from "lit/decorators.js";
|
|
3
3
|
import { classMap as n } from "lit/directives/class-map.js";
|
|
4
4
|
import { styleMap as u } from "lit/directives/style-map.js";
|
|
5
|
-
import { K as m, d as v } from "../../../chunks/kt-element-
|
|
5
|
+
import { K as m, d as v } from "../../../chunks/kt-element-mdd5cXZX.js";
|
|
6
6
|
import { e as b } from "../../../chunks/events-Bjl5Zmmq.js";
|
|
7
7
|
import { h as p } from "../../../chunks/slots-BPbIdxAJ.js";
|
|
8
8
|
var y = Object.defineProperty, i = (s, e, c, k) => {
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import { css as
|
|
2
|
-
import { state as
|
|
3
|
-
import { K as
|
|
1
|
+
import { css as b, nothing as s, html as d } from "lit";
|
|
2
|
+
import { state as m, property as c } from "lit/decorators.js";
|
|
3
|
+
import { K as h, d as v } from "../../../chunks/kt-element-mdd5cXZX.js";
|
|
4
4
|
import { e as g } from "../../../chunks/events-Bjl5Zmmq.js";
|
|
5
|
+
import { s as r } from "../../../chunks/index-fzPIgxe2.js";
|
|
5
6
|
import "../kt-icon/kt-icon.js";
|
|
6
|
-
var
|
|
7
|
-
for (var e = void 0,
|
|
8
|
-
(
|
|
9
|
-
return e &&
|
|
7
|
+
var y = Object.defineProperty, a = (p, o, n, x) => {
|
|
8
|
+
for (var e = void 0, i = p.length - 1, l; i >= 0; i--)
|
|
9
|
+
(l = p[i]) && (e = l(o, n, e) || e);
|
|
10
|
+
return e && y(o, n, e), e;
|
|
10
11
|
};
|
|
11
|
-
const t = class
|
|
12
|
+
const t = class u extends h {
|
|
12
13
|
constructor() {
|
|
13
14
|
super(...arguments), this.copied = !1, this.language = "", this.copy = !1, this.label = "";
|
|
14
15
|
}
|
|
15
16
|
static {
|
|
16
17
|
this.styles = [
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
h.styles,
|
|
19
|
+
b`
|
|
19
20
|
:host {
|
|
20
21
|
display: block;
|
|
21
22
|
}
|
|
@@ -106,50 +107,50 @@ const t = class h extends l {
|
|
|
106
107
|
try {
|
|
107
108
|
await navigator.clipboard.writeText(this.code), this.copied = !0, this.copiedTimer !== void 0 && clearTimeout(this.copiedTimer), this.copiedTimer = setTimeout(() => {
|
|
108
109
|
this.copied = !1;
|
|
109
|
-
},
|
|
110
|
+
}, u.COPIED_MS);
|
|
110
111
|
} catch {
|
|
111
112
|
}
|
|
112
113
|
g(this, "kt-copy", { code: this.code });
|
|
113
114
|
}
|
|
114
115
|
render() {
|
|
115
116
|
const o = !!this.language || this.copy;
|
|
116
|
-
return
|
|
117
|
-
${o ?
|
|
117
|
+
return d`<div part="base" class=${o ? "base" : "base bare"}>
|
|
118
|
+
${o ? d`<div part="header" class="header">
|
|
118
119
|
<span class="language">${this.language}</span>
|
|
119
|
-
${this.copy ?
|
|
120
|
+
${this.copy ? d`<button
|
|
120
121
|
type="button"
|
|
121
122
|
class=${this.copied ? "copy copied" : "copy"}
|
|
122
|
-
aria-label=${this.copied ?
|
|
123
|
+
aria-label=${this.copied ? r().copied : r().copyCode}
|
|
123
124
|
@click=${this.copyToClipboard}
|
|
124
125
|
>
|
|
125
126
|
<kt-icon name=${this.copied ? "check" : "copy"} size="14"></kt-icon>
|
|
126
|
-
${this.copied ?
|
|
127
|
-
</button>` :
|
|
128
|
-
</div>` :
|
|
127
|
+
${this.copied ? r().copied : r().copy}
|
|
128
|
+
</button>` : s}
|
|
129
|
+
</div>` : s}
|
|
129
130
|
|
|
130
131
|
<pre
|
|
131
132
|
part="pre"
|
|
132
133
|
tabindex="0"
|
|
133
|
-
aria-label=${this.label ||
|
|
134
|
+
aria-label=${this.label || s}
|
|
134
135
|
><code><slot></slot></code></pre>
|
|
135
136
|
</div>`;
|
|
136
137
|
}
|
|
137
138
|
};
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
a([
|
|
140
|
+
m()
|
|
140
141
|
], t.prototype, "copied");
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
a([
|
|
143
|
+
c({ type: String })
|
|
143
144
|
], t.prototype, "language");
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
a([
|
|
146
|
+
c({ type: Boolean })
|
|
146
147
|
], t.prototype, "copy");
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
a([
|
|
149
|
+
c({ type: String })
|
|
149
150
|
], t.prototype, "label");
|
|
150
|
-
let
|
|
151
|
-
v("kt-code",
|
|
151
|
+
let f = t;
|
|
152
|
+
v("kt-code", f);
|
|
152
153
|
export {
|
|
153
|
-
|
|
154
|
+
f as KtCode
|
|
154
155
|
};
|
|
155
156
|
//# sourceMappingURL=kt-code.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kt-code.js","sources":["../../../../src/components/core/kt-code/kt-code.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport '../kt-icon/kt-icon.js';\n\n/**\n * A block of code on a recessed surface, with its language and a copy button.\n *\n * The element owns the chrome — surface, label, scrolling, copy — and nothing\n * else. **Highlighting is the caller's**: slot in whatever markup a highlighter\n * produced, or plain text for none. A design system that bundled a syntax\n * highlighter would be picking your bundle size and your language set for you.\n *\n * ```html\n * <kt-code language=\"js\">const total = items.length;</kt-code>\n *\n * <kt-code language=\"ts\" copy>\n * <span class=\"hljs-keyword\">const</span> total = items.length;\n * </kt-code>\n * ```\n *\n * For a token or an identifier inside a sentence, reach for\n * `<kt-badge variant=\"code\">` instead — this is for blocks.\n *\n * @element kt-code\n *\n * @slot - The code. Plain text, or a highlighter's markup.\n *\n * @csspart base - The container.\n * @csspart header - The language row.\n * @csspart pre - The scrolling `<pre>`.\n *\n * @fires kt-copy - The copy button was pressed. `detail: { code }`.\n */\nexport class KtCode extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n .base {\n overflow: hidden;\n background: var(--surface-code);\n border: var(--border-width) solid var(--border-code);\n border-radius: var(--border-radius);\n }\n\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--gap-button);\n padding: 6px 8px 6px 14px;\n border-bottom: var(--border-width) solid var(--border-code);\n }\n\n .language {\n color: var(--text-muted);\n font: var(--font-normal-small);\n letter-spacing: 1px;\n text-transform: uppercase;\n }\n\n .copy {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n color: var(--text-muted);\n font: var(--font-normal-small);\n background: transparent;\n border: none;\n border-radius: 5px;\n cursor: pointer;\n transition:\n color var(--duration-instant),\n background-color var(--duration-instant);\n }\n\n .copy:hover {\n color: var(--text-body);\n background: var(--surface-raised);\n }\n\n .copy:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n .copied {\n color: var(--color-success-text);\n }\n\n pre {\n margin: 0;\n padding: 14px;\n overflow-x: auto;\n scrollbar-width: thin;\n }\n\n code {\n font: var(--font-code-regular);\n color: var(--text-code);\n }\n\n /* A block with no header should not leave a stray rule behind. */\n .bare pre {\n padding-top: 14px;\n }\n `,\n ];\n\n /** How long the copy button stays in its confirmed state. */\n private static readonly COPIED_MS = 1600;\n\n private copiedTimer: ReturnType<typeof setTimeout> | undefined;\n\n @state()\n private copied = false;\n\n /** Language label, shown uppercase. Purely informative. */\n @property({ type: String })\n language = '';\n\n /** Shows the copy button. */\n @property({ type: Boolean })\n copy = false;\n\n /** Accessible name for the block, when the language alone is not enough. */\n @property({ type: String })\n label = '';\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.copiedTimer !== undefined) clearTimeout(this.copiedTimer);\n }\n\n /** The code as plain text, whatever markup it is wrapped in. */\n get code(): string {\n return (this.textContent ?? '').replace(/^\\n+|\\n+$/g, '');\n }\n\n private async copyToClipboard(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.code);\n this.copied = true;\n\n if (this.copiedTimer !== undefined) clearTimeout(this.copiedTimer);\n this.copiedTimer = setTimeout(() => {\n this.copied = false;\n }, KtCode.COPIED_MS);\n } catch {\n // Denied permission, or an insecure origin. Nothing useful to show, and\n // failing loudly over a convenience button helps no one.\n }\n emit(this, 'kt-copy', { code: this.code });\n }\n\n override render(): TemplateResult {\n const hasHeader = Boolean(this.language) || this.copy;\n\n return html`<div part=\"base\" class=${hasHeader ? 'base' : 'base bare'}>\n ${\n hasHeader\n ? html`<div part=\"header\" class=\"header\">\n <span class=\"language\">${this.language}</span>\n ${\n this.copy\n ? html`<button\n type=\"button\"\n class=${this.copied ? 'copy copied' : 'copy'}\n aria-label=${this.copied ?
|
|
1
|
+
{"version":3,"file":"kt-code.js","sources":["../../../../src/components/core/kt-code/kt-code.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport { strings } from '#internal/strings';\nimport '../kt-icon/kt-icon.js';\n\n/**\n * A block of code on a recessed surface, with its language and a copy button.\n *\n * The element owns the chrome — surface, label, scrolling, copy — and nothing\n * else. **Highlighting is the caller's**: slot in whatever markup a highlighter\n * produced, or plain text for none. A design system that bundled a syntax\n * highlighter would be picking your bundle size and your language set for you.\n *\n * ```html\n * <kt-code language=\"js\">const total = items.length;</kt-code>\n *\n * <kt-code language=\"ts\" copy>\n * <span class=\"hljs-keyword\">const</span> total = items.length;\n * </kt-code>\n * ```\n *\n * For a token or an identifier inside a sentence, reach for\n * `<kt-badge variant=\"code\">` instead — this is for blocks.\n *\n * @element kt-code\n *\n * @slot - The code. Plain text, or a highlighter's markup.\n *\n * @csspart base - The container.\n * @csspart header - The language row.\n * @csspart pre - The scrolling `<pre>`.\n *\n * @fires kt-copy - The copy button was pressed. `detail: { code }`.\n */\nexport class KtCode extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n .base {\n overflow: hidden;\n background: var(--surface-code);\n border: var(--border-width) solid var(--border-code);\n border-radius: var(--border-radius);\n }\n\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--gap-button);\n padding: 6px 8px 6px 14px;\n border-bottom: var(--border-width) solid var(--border-code);\n }\n\n .language {\n color: var(--text-muted);\n font: var(--font-normal-small);\n letter-spacing: 1px;\n text-transform: uppercase;\n }\n\n .copy {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n color: var(--text-muted);\n font: var(--font-normal-small);\n background: transparent;\n border: none;\n border-radius: 5px;\n cursor: pointer;\n transition:\n color var(--duration-instant),\n background-color var(--duration-instant);\n }\n\n .copy:hover {\n color: var(--text-body);\n background: var(--surface-raised);\n }\n\n .copy:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n .copied {\n color: var(--color-success-text);\n }\n\n pre {\n margin: 0;\n padding: 14px;\n overflow-x: auto;\n scrollbar-width: thin;\n }\n\n code {\n font: var(--font-code-regular);\n color: var(--text-code);\n }\n\n /* A block with no header should not leave a stray rule behind. */\n .bare pre {\n padding-top: 14px;\n }\n `,\n ];\n\n /** How long the copy button stays in its confirmed state. */\n private static readonly COPIED_MS = 1600;\n\n private copiedTimer: ReturnType<typeof setTimeout> | undefined;\n\n @state()\n private copied = false;\n\n /** Language label, shown uppercase. Purely informative. */\n @property({ type: String })\n language = '';\n\n /** Shows the copy button. */\n @property({ type: Boolean })\n copy = false;\n\n /** Accessible name for the block, when the language alone is not enough. */\n @property({ type: String })\n label = '';\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.copiedTimer !== undefined) clearTimeout(this.copiedTimer);\n }\n\n /** The code as plain text, whatever markup it is wrapped in. */\n get code(): string {\n return (this.textContent ?? '').replace(/^\\n+|\\n+$/g, '');\n }\n\n private async copyToClipboard(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.code);\n this.copied = true;\n\n if (this.copiedTimer !== undefined) clearTimeout(this.copiedTimer);\n this.copiedTimer = setTimeout(() => {\n this.copied = false;\n }, KtCode.COPIED_MS);\n } catch {\n // Denied permission, or an insecure origin. Nothing useful to show, and\n // failing loudly over a convenience button helps no one.\n }\n emit(this, 'kt-copy', { code: this.code });\n }\n\n override render(): TemplateResult {\n const hasHeader = Boolean(this.language) || this.copy;\n\n return html`<div part=\"base\" class=${hasHeader ? 'base' : 'base bare'}>\n ${\n hasHeader\n ? html`<div part=\"header\" class=\"header\">\n <span class=\"language\">${this.language}</span>\n ${\n this.copy\n ? html`<button\n type=\"button\"\n class=${this.copied ? 'copy copied' : 'copy'}\n aria-label=${this.copied ? strings().copied : strings().copyCode}\n @click=${this.copyToClipboard}\n >\n <kt-icon name=${this.copied ? 'check' : 'copy'} size=\"14\"></kt-icon>\n ${this.copied ? strings().copied : strings().copy}\n </button>`\n : nothing\n }\n </div>`\n : nothing\n }\n\n <pre\n part=\"pre\"\n tabindex=\"0\"\n aria-label=${this.label || nothing}\n ><code><slot></slot></code></pre>\n </div>`;\n }\n}\n\ndefineElement('kt-code', KtCode);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-code': KtCode;\n }\n}\n"],"names":["_KtCode","KtElement","css","emit","hasHeader","html","strings","nothing","__decorateClass","state","property","KtCode","defineElement"],"mappings":";;;;;;;;;;;AAoCO,MAAMA,IAAN,MAAMA,UAAeC,EAAU;AAAA,EAA/B,cAAA;AAAA,UAAA,GAAA,SAAA,GAsFL,KAAQ,SAAS,IAIjB,KAAA,WAAW,IAIX,KAAA,OAAO,IAIP,KAAA,QAAQ;AAAA,EAAA;AAAA,EAjGR,OAAA;AAAA,SAAgB,SAAS;AAAA,MACvBA,EAAU;AAAA,MACVC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,EA2EF;AAAA,EAGA,OAAA;AAAA,SAAwB,YAAY;AAAA,EAAA;AAAA,EAmB3B,uBAA6B;AACpC,UAAM,qBAAA,GACF,KAAK,gBAAgB,UAAW,aAAa,KAAK,WAAW;AAAA,EACnE;AAAA;AAAA,EAGA,IAAI,OAAe;AACjB,YAAQ,KAAK,eAAe,IAAI,QAAQ,cAAc,EAAE;AAAA,EAC1D;AAAA,EAEA,MAAc,kBAAiC;AAC7C,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,KAAK,IAAI,GAC7C,KAAK,SAAS,IAEV,KAAK,gBAAgB,UAAW,aAAa,KAAK,WAAW,GACjE,KAAK,cAAc,WAAW,MAAM;AAClC,aAAK,SAAS;AAAA,MAChB,GAAGF,EAAO,SAAS;AAAA,IACrB,QAAQ;AAAA,IAGR;AACA,IAAAG,EAAK,MAAM,WAAW,EAAE,MAAM,KAAK,MAAM;AAAA,EAC3C;AAAA,EAES,SAAyB;AAChC,UAAMC,IAAY,EAAQ,KAAK,YAAa,KAAK;AAEjD,WAAOC,2BAA8BD,IAAY,SAAS,WAAW;AAAA,QAEjEA,IACIC;AAAA,uCAC2B,KAAK,QAAQ;AAAA,gBAEpC,KAAK,OACDA;AAAA;AAAA,8BAEU,KAAK,SAAS,gBAAgB,MAAM;AAAA,mCAC/B,KAAK,SAASC,EAAA,EAAU,SAASA,EAAA,EAAU,QAAQ;AAAA,+BACvD,KAAK,eAAe;AAAA;AAAA,sCAEb,KAAK,SAAS,UAAU,MAAM;AAAA,wBAC5C,KAAK,SAASA,EAAA,EAAU,SAASA,EAAA,EAAU,IAAI;AAAA,iCAEnDC,CACN;AAAA,sBAEFA,CACN;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKe,KAAK,SAASA,CAAO;AAAA;AAAA;AAAA,EAGxC;AACF;AAxEUC,EAAA;AAAA,EADPC,EAAA;AAAM,GArFIT,EAsFH,WAAA,QAAA;AAIRQ,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAzFfV,EA0FX,WAAA,UAAA;AAIAQ,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GA7FhBV,EA8FX,WAAA,MAAA;AAIAQ,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAjGfV,EAkGX,WAAA,OAAA;AAlGK,IAAMW,IAANX;AAgKPY,EAAc,WAAWD,CAAM;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { css as f, html as c, nothing as l } from "lit";
|
|
2
2
|
import { property as n } from "lit/decorators.js";
|
|
3
|
-
import { K as m, d as u } from "../../../chunks/kt-element-
|
|
3
|
+
import { K as m, d as u } from "../../../chunks/kt-element-mdd5cXZX.js";
|
|
4
4
|
import { g as v } from "../../../chunks/defaults-DKzFsNbv.js";
|
|
5
5
|
var w = Object.defineProperty, o = (i, e, r, h) => {
|
|
6
6
|
for (var t = void 0, a = i.length - 1, d; a >= 0; a--)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { css as c, html as i } from "lit";
|
|
2
2
|
import { property as p } from "lit/decorators.js";
|
|
3
|
-
import { K as l, d as m } from "../../../chunks/kt-element-
|
|
3
|
+
import { K as l, d as m } from "../../../chunks/kt-element-mdd5cXZX.js";
|
|
4
4
|
var f = Object.defineProperty, d = (a, t, e, u) => {
|
|
5
5
|
for (var r = void 0, s = a.length - 1, o; s >= 0; s--)
|
|
6
6
|
(o = a[s]) && (r = o(t, e, r) || r);
|
|
@@ -64,10 +64,10 @@ export declare class KtSplitButton extends KtElement {
|
|
|
64
64
|
/** Lucide icon name for the primary segment. */
|
|
65
65
|
icon: string;
|
|
66
66
|
/** Accessible name of the caret, which has no text of its own. */
|
|
67
|
-
menuLabel: string;
|
|
67
|
+
menuLabel: string | undefined;
|
|
68
68
|
/** Where to put the menu when there is room on both sides. */
|
|
69
69
|
preferredPlacement: KtDropdownPlacement;
|
|
70
|
-
emptyText: string;
|
|
70
|
+
emptyText: string | undefined;
|
|
71
71
|
/** Whether the menu is showing. */
|
|
72
72
|
get isOpen(): boolean;
|
|
73
73
|
/** Opens the menu. */
|