luxen-ui 0.11.0 → 0.11.1
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/cdn/custom-elements.json +118 -96
- package/cdn/elements/dropdown-item/dropdown-item.js +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.js.map +1 -1
- package/cdn/elements/tabs/tabs.d.ts +5 -0
- package/cdn/elements/tabs/tabs.d.ts.map +1 -1
- package/cdn/elements/tabs/tabs.js.map +1 -1
- package/cdn/standalone.css +4 -4
- package/cdn/standalone.js +6 -1
- package/cdn/standalone.js.map +1 -1
- package/cdn/styles/elements/tabs/line.css +4 -4
- package/dist/css/elements/tabs/line.css +4 -4
- package/dist/custom-elements.json +118 -96
- package/dist/elements/dropdown-item/dropdown-item.css +2 -0
- package/dist/elements/tabs/tabs.d.ts +5 -0
- package/dist/elements/tabs/tabs.d.ts.map +1 -1
- package/dist/elements/tabs/tabs.js +5 -0
- package/dist/metadata/index.json +23 -2
- package/dist/metadata/tabs.json +22 -1
- package/dist/templates/elements/tabs.md +29 -0
- package/package.json +1 -1
package/cdn/custom-elements.json
CHANGED
|
@@ -1198,102 +1198,6 @@
|
|
|
1198
1198
|
}
|
|
1199
1199
|
]
|
|
1200
1200
|
},
|
|
1201
|
-
{
|
|
1202
|
-
"kind": "javascript-module",
|
|
1203
|
-
"path": "src/html/elements/close-button/close-button.meta.ts",
|
|
1204
|
-
"declarations": [
|
|
1205
|
-
{
|
|
1206
|
-
"kind": "class",
|
|
1207
|
-
"description": "",
|
|
1208
|
-
"name": "CloseButtonMeta",
|
|
1209
|
-
"cssProperties": [
|
|
1210
|
-
{
|
|
1211
|
-
"description": "Button size.",
|
|
1212
|
-
"name": "--size",
|
|
1213
|
-
"default": "36px"
|
|
1214
|
-
},
|
|
1215
|
-
{
|
|
1216
|
-
"description": "Icon color.",
|
|
1217
|
-
"name": "--icon-color"
|
|
1218
|
-
},
|
|
1219
|
-
{
|
|
1220
|
-
"description": "Icon size.",
|
|
1221
|
-
"name": "--icon-size",
|
|
1222
|
-
"default": "24px"
|
|
1223
|
-
},
|
|
1224
|
-
{
|
|
1225
|
-
"description": "Hover ring color (`ring` appearance only).",
|
|
1226
|
-
"name": "--ring-color"
|
|
1227
|
-
},
|
|
1228
|
-
{
|
|
1229
|
-
"description": "Hover ring thickness (`ring` appearance only).",
|
|
1230
|
-
"name": "--ring-tickness"
|
|
1231
|
-
}
|
|
1232
|
-
],
|
|
1233
|
-
"attributes": [
|
|
1234
|
-
{
|
|
1235
|
-
"description": "ring | square | circle — Visual appearance (matches the imported appearance CSS).",
|
|
1236
|
-
"name": "data-appearance"
|
|
1237
|
-
},
|
|
1238
|
-
{
|
|
1239
|
-
"description": "Invoker command (typically `close`).",
|
|
1240
|
-
"name": "command"
|
|
1241
|
-
},
|
|
1242
|
-
{
|
|
1243
|
-
"description": "ID of the target element to close.",
|
|
1244
|
-
"name": "commandfor"
|
|
1245
|
-
}
|
|
1246
|
-
],
|
|
1247
|
-
"summary": "A circular/square icon button that renders an X via CSS mask, for dismissing dialogs and panels.",
|
|
1248
|
-
"examples": [
|
|
1249
|
-
{
|
|
1250
|
-
"title": "Ring appearance",
|
|
1251
|
-
"language": "html",
|
|
1252
|
-
"code": "<button class=\"l-close\" data-appearance=\"ring\" aria-label=\"Close\"></button>"
|
|
1253
|
-
}
|
|
1254
|
-
],
|
|
1255
|
-
"_cssClasses": [
|
|
1256
|
-
{
|
|
1257
|
-
"name": ".l-close",
|
|
1258
|
-
"description": "Base close button with X icon via CSS mask."
|
|
1259
|
-
}
|
|
1260
|
-
],
|
|
1261
|
-
"customElement": false,
|
|
1262
|
-
"_native": true,
|
|
1263
|
-
"_nativeTag": "button",
|
|
1264
|
-
"selector": ".l-close",
|
|
1265
|
-
"_attributes": [
|
|
1266
|
-
{
|
|
1267
|
-
"name": "data-appearance",
|
|
1268
|
-
"values": [
|
|
1269
|
-
"ring",
|
|
1270
|
-
"square",
|
|
1271
|
-
"circle"
|
|
1272
|
-
],
|
|
1273
|
-
"description": "Visual appearance (matches the imported appearance CSS)."
|
|
1274
|
-
},
|
|
1275
|
-
{
|
|
1276
|
-
"name": "command",
|
|
1277
|
-
"description": "Invoker command (typically `close`)."
|
|
1278
|
-
},
|
|
1279
|
-
{
|
|
1280
|
-
"name": "commandfor",
|
|
1281
|
-
"description": "ID of the target element to close."
|
|
1282
|
-
}
|
|
1283
|
-
]
|
|
1284
|
-
}
|
|
1285
|
-
],
|
|
1286
|
-
"exports": [
|
|
1287
|
-
{
|
|
1288
|
-
"kind": "js",
|
|
1289
|
-
"name": "CloseButtonMeta",
|
|
1290
|
-
"declaration": {
|
|
1291
|
-
"name": "CloseButtonMeta",
|
|
1292
|
-
"module": "src/html/elements/close-button/close-button.meta.ts"
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
]
|
|
1296
|
-
},
|
|
1297
1201
|
{
|
|
1298
1202
|
"kind": "javascript-module",
|
|
1299
1203
|
"path": "src/html/elements/checkbox/checkbox.meta.ts",
|
|
@@ -1398,6 +1302,102 @@
|
|
|
1398
1302
|
}
|
|
1399
1303
|
]
|
|
1400
1304
|
},
|
|
1305
|
+
{
|
|
1306
|
+
"kind": "javascript-module",
|
|
1307
|
+
"path": "src/html/elements/close-button/close-button.meta.ts",
|
|
1308
|
+
"declarations": [
|
|
1309
|
+
{
|
|
1310
|
+
"kind": "class",
|
|
1311
|
+
"description": "",
|
|
1312
|
+
"name": "CloseButtonMeta",
|
|
1313
|
+
"cssProperties": [
|
|
1314
|
+
{
|
|
1315
|
+
"description": "Button size.",
|
|
1316
|
+
"name": "--size",
|
|
1317
|
+
"default": "36px"
|
|
1318
|
+
},
|
|
1319
|
+
{
|
|
1320
|
+
"description": "Icon color.",
|
|
1321
|
+
"name": "--icon-color"
|
|
1322
|
+
},
|
|
1323
|
+
{
|
|
1324
|
+
"description": "Icon size.",
|
|
1325
|
+
"name": "--icon-size",
|
|
1326
|
+
"default": "24px"
|
|
1327
|
+
},
|
|
1328
|
+
{
|
|
1329
|
+
"description": "Hover ring color (`ring` appearance only).",
|
|
1330
|
+
"name": "--ring-color"
|
|
1331
|
+
},
|
|
1332
|
+
{
|
|
1333
|
+
"description": "Hover ring thickness (`ring` appearance only).",
|
|
1334
|
+
"name": "--ring-tickness"
|
|
1335
|
+
}
|
|
1336
|
+
],
|
|
1337
|
+
"attributes": [
|
|
1338
|
+
{
|
|
1339
|
+
"description": "ring | square | circle — Visual appearance (matches the imported appearance CSS).",
|
|
1340
|
+
"name": "data-appearance"
|
|
1341
|
+
},
|
|
1342
|
+
{
|
|
1343
|
+
"description": "Invoker command (typically `close`).",
|
|
1344
|
+
"name": "command"
|
|
1345
|
+
},
|
|
1346
|
+
{
|
|
1347
|
+
"description": "ID of the target element to close.",
|
|
1348
|
+
"name": "commandfor"
|
|
1349
|
+
}
|
|
1350
|
+
],
|
|
1351
|
+
"summary": "A circular/square icon button that renders an X via CSS mask, for dismissing dialogs and panels.",
|
|
1352
|
+
"examples": [
|
|
1353
|
+
{
|
|
1354
|
+
"title": "Ring appearance",
|
|
1355
|
+
"language": "html",
|
|
1356
|
+
"code": "<button class=\"l-close\" data-appearance=\"ring\" aria-label=\"Close\"></button>"
|
|
1357
|
+
}
|
|
1358
|
+
],
|
|
1359
|
+
"_cssClasses": [
|
|
1360
|
+
{
|
|
1361
|
+
"name": ".l-close",
|
|
1362
|
+
"description": "Base close button with X icon via CSS mask."
|
|
1363
|
+
}
|
|
1364
|
+
],
|
|
1365
|
+
"customElement": false,
|
|
1366
|
+
"_native": true,
|
|
1367
|
+
"_nativeTag": "button",
|
|
1368
|
+
"selector": ".l-close",
|
|
1369
|
+
"_attributes": [
|
|
1370
|
+
{
|
|
1371
|
+
"name": "data-appearance",
|
|
1372
|
+
"values": [
|
|
1373
|
+
"ring",
|
|
1374
|
+
"square",
|
|
1375
|
+
"circle"
|
|
1376
|
+
],
|
|
1377
|
+
"description": "Visual appearance (matches the imported appearance CSS)."
|
|
1378
|
+
},
|
|
1379
|
+
{
|
|
1380
|
+
"name": "command",
|
|
1381
|
+
"description": "Invoker command (typically `close`)."
|
|
1382
|
+
},
|
|
1383
|
+
{
|
|
1384
|
+
"name": "commandfor",
|
|
1385
|
+
"description": "ID of the target element to close."
|
|
1386
|
+
}
|
|
1387
|
+
]
|
|
1388
|
+
}
|
|
1389
|
+
],
|
|
1390
|
+
"exports": [
|
|
1391
|
+
{
|
|
1392
|
+
"kind": "js",
|
|
1393
|
+
"name": "CloseButtonMeta",
|
|
1394
|
+
"declaration": {
|
|
1395
|
+
"name": "CloseButtonMeta",
|
|
1396
|
+
"module": "src/html/elements/close-button/close-button.meta.ts"
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
]
|
|
1400
|
+
},
|
|
1401
1401
|
{
|
|
1402
1402
|
"kind": "javascript-module",
|
|
1403
1403
|
"path": "src/html/elements/dialog/dialog.ts",
|
|
@@ -5477,6 +5477,28 @@
|
|
|
5477
5477
|
"kind": "class",
|
|
5478
5478
|
"description": "",
|
|
5479
5479
|
"name": "Tabs",
|
|
5480
|
+
"cssProperties": [
|
|
5481
|
+
{
|
|
5482
|
+
"description": "`line` variant: color of the active underline that slides under the selected tab.",
|
|
5483
|
+
"name": "--indicator-color",
|
|
5484
|
+
"default": "var(--l-color-text-primary)"
|
|
5485
|
+
},
|
|
5486
|
+
{
|
|
5487
|
+
"description": "`line` variant: thickness of the active underline.",
|
|
5488
|
+
"name": "--indicator-thickness",
|
|
5489
|
+
"default": "2px"
|
|
5490
|
+
},
|
|
5491
|
+
{
|
|
5492
|
+
"description": "`line` variant: color of the static bottom border the tabs sit on.",
|
|
5493
|
+
"name": "--track-color",
|
|
5494
|
+
"default": "var(--l-color-border)"
|
|
5495
|
+
},
|
|
5496
|
+
{
|
|
5497
|
+
"description": "`line` variant: thickness of the static bottom border.",
|
|
5498
|
+
"name": "--track-thickness",
|
|
5499
|
+
"default": "1px"
|
|
5500
|
+
}
|
|
5501
|
+
],
|
|
5480
5502
|
"members": [
|
|
5481
5503
|
{
|
|
5482
5504
|
"kind": "field",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e}from"../../chunks/lit.js";import{a as t,t as n}from"../../chunks/lit-html.js";import{LuxenElement as r}from"../../shared/luxen-element.js";import{i,t as a}from"../../chunks/decorate.js";import o from"../../shared/styles/host.styles.js";var s=e(`:host{display:block}:host([disabled]){pointer-events:none;opacity:.5}.item{cursor:pointer;color:var(--l-color-text-primary,CanvasText);white-space:nowrap;text-align:start;border-radius:4px;outline:none;align-items:center;gap:8px;padding:.375rem .5rem;font-size:.875rem;line-height:1.5;display:flex}.item:focus-visible{background:var(--l-color-bg-state-hover)}@media (hover:hover){.item:hover{background:var(--l-color-bg-state-hover)}}.check{flex-shrink:0;width:16px;display:flex}:host(:not([checked])) .check svg{visibility:hidden}::slotted([slot=prefix]),::slotted([slot=suffix]){flex-shrink:0;display:flex}.label{flex:1}`),c=class extends r{static{this.styles=[o,s]}#e=``;get value(){return this.#e}set value(e){this.#e=e}#t=!1;get disabled(){return this.#t}set disabled(e){this.#t=e}#n=`normal`;get type(){return this.#n}set type(e){this.#n=e}#r=!1;get checked(){return this.#r}set checked(e){this.#r=e}getTextLabel(){return(this.textContent??``).trim()}render(){let e=this.type===`checkbox`;return t`
|
|
1
|
+
import{i as e}from"../../chunks/lit.js";import{a as t,t as n}from"../../chunks/lit-html.js";import{LuxenElement as r}from"../../shared/luxen-element.js";import{i,t as a}from"../../chunks/decorate.js";import o from"../../shared/styles/host.styles.js";var s=e(`:host{display:block}:host([disabled]){pointer-events:none;opacity:.5}.item{box-sizing:border-box;cursor:pointer;min-block-size:36px;color:var(--l-color-text-primary,CanvasText);white-space:nowrap;text-align:start;border-radius:4px;outline:none;align-items:center;gap:8px;padding:.375rem .5rem;font-size:.875rem;line-height:1.5;display:flex}.item:focus-visible{background:var(--l-color-bg-state-hover)}@media (hover:hover){.item:hover{background:var(--l-color-bg-state-hover)}}.check{flex-shrink:0;width:16px;display:flex}:host(:not([checked])) .check svg{visibility:hidden}::slotted([slot=prefix]),::slotted([slot=suffix]){flex-shrink:0;display:flex}.label{flex:1}`),c=class extends r{static{this.styles=[o,s]}#e=``;get value(){return this.#e}set value(e){this.#e=e}#t=!1;get disabled(){return this.#t}set disabled(e){this.#t=e}#n=`normal`;get type(){return this.#n}set type(e){this.#n=e}#r=!1;get checked(){return this.#r}set checked(e){this.#r=e}getTextLabel(){return(this.textContent??``).trim()}render(){let e=this.type===`checkbox`;return t`
|
|
2
2
|
<div
|
|
3
3
|
class="item"
|
|
4
4
|
role=${e?`menuitemcheckbox`:`menuitem`}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown-item.js","names":[],"sources":["../../../src/html/elements/dropdown-item/dropdown-item.css?inline","../../../src/html/elements/dropdown-item/dropdown-item.ts"],"sourcesContent":[":host {\n display: block;\n}\n\n:host([disabled]) {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0.375rem 0.5rem;\n cursor: pointer;\n outline: none;\n border-radius: 4px;\n font-size: 0.875rem;\n line-height: 1.5;\n color: var(--l-color-text-primary, CanvasText);\n white-space: nowrap;\n text-align: start;\n}\n\n.item:focus-visible {\n background: var(--l-color-bg-state-hover);\n}\n\n@media (hover: hover) {\n .item:hover {\n background: var(--l-color-bg-state-hover);\n }\n}\n\n.check {\n display: flex;\n width: 16px;\n flex-shrink: 0;\n}\n\n:host(:not([checked])) .check svg {\n visibility: hidden;\n}\n\n::slotted([slot='prefix']),\n::slotted([slot='suffix']) {\n display: flex;\n flex-shrink: 0;\n}\n\n.label {\n flex: 1;\n}\n","import { html, nothing, unsafeCSS } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { property } from 'lit/decorators.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './dropdown-item.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * A menu item for use inside `<l-dropdown>`.\n *\n * @slot - Label text.\n * @slot prefix - Leading content (e.g. icon).\n * @slot suffix - Trailing content.\n *\n * @cssproperty --color - Text color.\n *\n * @customElement l-dropdown-item\n */\nexport class DropdownItem extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n /** The value associated with this item. */\n @property()\n accessor value = '';\n\n /** Disables the item. */\n @property({ type: Boolean, reflect: true })\n accessor disabled = false;\n\n /** The type of item: `normal` or `checkbox`. */\n @property()\n accessor type: 'normal' | 'checkbox' = 'normal';\n\n /** Whether the checkbox item is checked. */\n @property({ type: Boolean, reflect: true })\n accessor checked = false;\n\n /** Returns the text label of this item. */\n getTextLabel(): string {\n return (this.textContent ?? '').trim();\n }\n\n override render() {\n const isCheckbox = this.type === 'checkbox';\n\n return html`\n <div\n class=\"item\"\n role=${isCheckbox ? 'menuitemcheckbox' : 'menuitem'}\n aria-checked=${isCheckbox ? String(this.checked) : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n tabindex=\"-1\"\n >\n ${isCheckbox\n ? html`\n <span\n class=\"check\"\n aria-hidden=\"true\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n `\n : html` <slot name=\"prefix\"></slot> `}\n <span class=\"label\"><slot></slot></span>\n <slot name=\"suffix\"></slot>\n </div>\n `;\n }\n}\n"],"mappings":"0PCMA,IAAM,EAAS,EAAU,
|
|
1
|
+
{"version":3,"file":"dropdown-item.js","names":[],"sources":["../../../src/html/elements/dropdown-item/dropdown-item.css?inline","../../../src/html/elements/dropdown-item/dropdown-item.ts"],"sourcesContent":[":host {\n display: block;\n}\n\n:host([disabled]) {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: 8px;\n box-sizing: border-box;\n min-block-size: 36px;\n padding: 0.375rem 0.5rem;\n cursor: pointer;\n outline: none;\n border-radius: 4px;\n font-size: 0.875rem;\n line-height: 1.5;\n color: var(--l-color-text-primary, CanvasText);\n white-space: nowrap;\n text-align: start;\n}\n\n.item:focus-visible {\n background: var(--l-color-bg-state-hover);\n}\n\n@media (hover: hover) {\n .item:hover {\n background: var(--l-color-bg-state-hover);\n }\n}\n\n.check {\n display: flex;\n width: 16px;\n flex-shrink: 0;\n}\n\n:host(:not([checked])) .check svg {\n visibility: hidden;\n}\n\n::slotted([slot='prefix']),\n::slotted([slot='suffix']) {\n display: flex;\n flex-shrink: 0;\n}\n\n.label {\n flex: 1;\n}\n","import { html, nothing, unsafeCSS } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { property } from 'lit/decorators.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './dropdown-item.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * A menu item for use inside `<l-dropdown>`.\n *\n * @slot - Label text.\n * @slot prefix - Leading content (e.g. icon).\n * @slot suffix - Trailing content.\n *\n * @cssproperty --color - Text color.\n *\n * @customElement l-dropdown-item\n */\nexport class DropdownItem extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n /** The value associated with this item. */\n @property()\n accessor value = '';\n\n /** Disables the item. */\n @property({ type: Boolean, reflect: true })\n accessor disabled = false;\n\n /** The type of item: `normal` or `checkbox`. */\n @property()\n accessor type: 'normal' | 'checkbox' = 'normal';\n\n /** Whether the checkbox item is checked. */\n @property({ type: Boolean, reflect: true })\n accessor checked = false;\n\n /** Returns the text label of this item. */\n getTextLabel(): string {\n return (this.textContent ?? '').trim();\n }\n\n override render() {\n const isCheckbox = this.type === 'checkbox';\n\n return html`\n <div\n class=\"item\"\n role=${isCheckbox ? 'menuitemcheckbox' : 'menuitem'}\n aria-checked=${isCheckbox ? String(this.checked) : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n tabindex=\"-1\"\n >\n ${isCheckbox\n ? html`\n <span\n class=\"check\"\n aria-hidden=\"true\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n `\n : html` <slot name=\"prefix\"></slot> `}\n <span class=\"label\"><slot></slot></span>\n <slot name=\"suffix\"></slot>\n </div>\n `;\n }\n}\n"],"mappings":"0PCMA,IAAM,EAAS,EAAU,2pBAAU,CAatB,EAAb,cAAkC,CAAa,oBACpB,CAAC,EAAY,EAAO,IAI5B,OAAR,OAAA,0CAIW,OAAX,UAAA,6CAI8B,aAA9B,MAAA,yCAIU,OAAV,SAAA,yCAGT,cAAuB,CACrB,OAAQ,KAAK,aAAe,IAAI,MAAM,CAGxC,QAAkB,CAChB,IAAM,EAAa,KAAK,OAAS,WAEjC,MAAO,EAAI;;;eAGA,EAAa,mBAAqB,WAAW;uBACrC,EAAa,OAAO,KAAK,QAAQ,CAAG,EAAQ;wBAC3C,KAAK,SAAW,OAAS,EAAQ;;;UAG/C,EACE,CAAI;;;;;;;;;;;;;;;;;;;;cAqBJ,CAAI,gCAAgC;;;;WArD7C,GAAU,CAAA,CAAA,EAAA,UAAA,QAAA,KAAA,IAIV,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,WAAA,KAAA,IAI1C,GAAU,CAAA,CAAA,EAAA,UAAA,OAAA,KAAA,IAIV,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,UAAA,KAAA"}
|
|
@@ -19,6 +19,11 @@ export type TabsOrientation = 'horizontal' | 'vertical';
|
|
|
19
19
|
*
|
|
20
20
|
* @event change - Fired when the active tab changes. Detail: `{ index: number, name: string | null }`.
|
|
21
21
|
*
|
|
22
|
+
* @cssproperty [--indicator-color=var(--l-color-text-primary)] - `line` variant: color of the active underline that slides under the selected tab.
|
|
23
|
+
* @cssproperty [--indicator-thickness=2px] - `line` variant: thickness of the active underline.
|
|
24
|
+
* @cssproperty [--track-color=var(--l-color-border)] - `line` variant: color of the static bottom border the tabs sit on.
|
|
25
|
+
* @cssproperty [--track-thickness=1px] - `line` variant: thickness of the static bottom border.
|
|
26
|
+
*
|
|
22
27
|
* @customElement l-tabs
|
|
23
28
|
*/
|
|
24
29
|
export declare class Tabs extends LuxenElement {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tabs/tabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,UAAU,CAAC;AAExD
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tabs/tabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,UAAU,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,IAAK,SAAQ,YAAY;IAC3B,gBAAgB;IAIzB,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,OAAO,CAAqB;IAEpC,sBAAsB;IAEtB,OAAO,EAAE,WAAW,CAAU;IAE9B,yCAAyC;IAEzC,KAAK,SAAO;IAEZ,4CAA4C;IAE5C,SAAS,UAAS;IAElB,uBAAuB;IAEvB,WAAW,EAAE,eAAe,CAAgB;IAInC,iBAAiB;IAMjB,oBAAoB;IAKpB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAW9C,OAAO,CAAC,MAAM;IAoDd,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,UAAU;IA2BlB,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,QAAQ,CAQd;IAEF,OAAO,CAAC,UAAU,CAkChB;CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.js","names":[],"sources":["../../../src/html/elements/tabs/tabs.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { uniqueId } from '../../registry.js';\n\nexport type TabsVariant = 'enclosed' | 'line';\nexport type TabsOrientation = 'horizontal' | 'vertical';\n\n/**\n * @summary A tabs component that progressively enhances light DOM markup\n * with ARIA roles, keyboard navigation, and animated indicators.\n *\n * @example\n * ```html\n * <l-tabs variant=\"enclosed\">\n * <div>\n * <button>Tab 1</button>\n * <button>Tab 2</button>\n * </div>\n * <div>Content 1</div>\n * <div>Content 2</div>\n * </l-tabs>\n * ```\n *\n * @event change - Fired when the active tab changes. Detail: `{ index: number, name: string | null }`.\n *\n * @customElement l-tabs\n */\nexport class Tabs extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n private _instanceId = uniqueId('tabs');\n private _tablistEl: HTMLElement | null = null;\n private _tabs: HTMLButtonElement[] = [];\n private _panels: HTMLElement[] = [];\n\n /** Visual variant. */\n @property({ reflect: true })\n variant: TabsVariant = 'line';\n\n /** Index of the active tab (0-based). */\n @property({ reflect: true })\n value = '0';\n\n /** Stretch tabs to fill container width. */\n @property({ type: Boolean, reflect: true, attribute: 'full-width' })\n fullWidth = false;\n\n /** Tab orientation. */\n @property({ reflect: true })\n orientation: TabsOrientation = 'horizontal';\n\n // --- Lifecycle ---\n\n override connectedCallback() {\n super.connectedCallback();\n // Defer setup to let light DOM children parse\n requestAnimationFrame(() => this._setup());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('value') && this._tabs.length) {\n this._selectTab(Number(this.value), false);\n }\n if (changed.has('orientation') && this._tablistEl) {\n this._tablistEl.setAttribute('aria-orientation', this.orientation);\n }\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n const children = Array.from(this.children) as HTMLElement[];\n if (children.length < 2) return;\n\n // First child is the tablist container\n this._tablistEl = children[0];\n this._tablistEl.setAttribute('role', 'tablist');\n this._tablistEl.setAttribute('aria-orientation', this.orientation);\n\n // Buttons inside tablist become tabs\n this._tabs = Array.from(this._tablistEl.querySelectorAll('button'));\n\n // Remaining children become panels\n this._panels = children.slice(1);\n\n const activeIndex = Number(this.value) || 0;\n\n // Enhance tabs\n for (let i = 0; i < this._tabs.length; i++) {\n const tab = this._tabs[i];\n const panel = this._panels[i];\n const name = tab.getAttribute('name') ?? String(i);\n const tabId = `${this._instanceId}-tab-${name}`;\n const panelId = `${this._instanceId}-panel-${name}`;\n\n tab.setAttribute('role', 'tab');\n tab.setAttribute('id', tabId);\n tab.setAttribute('aria-selected', String(i === activeIndex));\n tab.setAttribute('tabindex', i === activeIndex ? '0' : '-1');\n\n if (panel) {\n tab.setAttribute('aria-controls', panelId);\n panel.setAttribute('role', 'tabpanel');\n panel.setAttribute('id', panelId);\n panel.setAttribute('aria-labelledby', tabId);\n panel.setAttribute('tabindex', '0');\n if (i !== activeIndex) {\n panel.hidden = true;\n } else {\n panel.hidden = false;\n }\n }\n }\n\n // Attach listeners\n this._tablistEl.addEventListener('click', this._onClick);\n this._tablistEl.addEventListener('keydown', this._onKeyDown);\n\n // Initial indicator position\n requestAnimationFrame(() => this._updateIndicator());\n }\n\n private _teardown() {\n this._tablistEl?.removeEventListener('click', this._onClick);\n this._tablistEl?.removeEventListener('keydown', this._onKeyDown);\n }\n\n // --- Tab selection ---\n\n private _selectTab(index: number, emitEvent = true) {\n if (index < 0 || index >= this._tabs.length) return;\n\n for (let i = 0; i < this._tabs.length; i++) {\n const tab = this._tabs[i];\n const panel = this._panels[i];\n const isActive = i === index;\n\n tab.setAttribute('aria-selected', String(isActive));\n tab.setAttribute('tabindex', isActive ? '0' : '-1');\n\n if (panel) {\n panel.hidden = !isActive;\n }\n }\n\n this.value = String(index);\n this._updateIndicator();\n\n if (emitEvent) {\n const name = this._tabs[index]?.getAttribute('name') ?? null;\n this.emit('change', { detail: { index, name } });\n }\n }\n\n // --- Indicator ---\n\n private _updateIndicator() {\n if (!this._tablistEl) return;\n const activeTab = this._tabs[Number(this.value)];\n if (!activeTab) return;\n\n const isVertical = this.orientation === 'vertical';\n\n if (isVertical) {\n this._tablistEl.style.setProperty('--_indicator-top', `${activeTab.offsetTop}px`);\n this._tablistEl.style.setProperty('--_indicator-height', `${activeTab.offsetHeight}px`);\n } else {\n this._tablistEl.style.setProperty('--_indicator-left', `${activeTab.offsetLeft}px`);\n this._tablistEl.style.setProperty('--_indicator-width', `${activeTab.offsetWidth}px`);\n }\n }\n\n // --- Event handlers ---\n\n private _onClick = (e: Event) => {\n const tab = (e.target as HTMLElement).closest<HTMLButtonElement>('[role=\"tab\"]');\n if (!tab) return;\n const index = this._tabs.indexOf(tab);\n if (index >= 0) {\n this._selectTab(index);\n tab.focus();\n }\n };\n\n private _onKeyDown = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement;\n if (target.getAttribute('role') !== 'tab') return;\n\n const isHorizontal = this.orientation === 'horizontal';\n const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';\n const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';\n\n let index = this._tabs.indexOf(target as HTMLButtonElement);\n\n switch (e.key) {\n case nextKey:\n e.preventDefault();\n index = (index + 1) % this._tabs.length;\n this._selectTab(index);\n this._tabs[index].focus();\n break;\n case prevKey:\n e.preventDefault();\n index = (index - 1 + this._tabs.length) % this._tabs.length;\n this._selectTab(index);\n this._tabs[index].focus();\n break;\n case 'Home':\n e.preventDefault();\n this._selectTab(0);\n this._tabs[0].focus();\n break;\n case 'End':\n e.preventDefault();\n this._selectTab(this._tabs.length - 1);\n this._tabs[this._tabs.length - 1].focus();\n break;\n }\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tabs.js","names":[],"sources":["../../../src/html/elements/tabs/tabs.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { uniqueId } from '../../registry.js';\n\nexport type TabsVariant = 'enclosed' | 'line';\nexport type TabsOrientation = 'horizontal' | 'vertical';\n\n/**\n * @summary A tabs component that progressively enhances light DOM markup\n * with ARIA roles, keyboard navigation, and animated indicators.\n *\n * @example\n * ```html\n * <l-tabs variant=\"enclosed\">\n * <div>\n * <button>Tab 1</button>\n * <button>Tab 2</button>\n * </div>\n * <div>Content 1</div>\n * <div>Content 2</div>\n * </l-tabs>\n * ```\n *\n * @event change - Fired when the active tab changes. Detail: `{ index: number, name: string | null }`.\n *\n * @cssproperty [--indicator-color=var(--l-color-text-primary)] - `line` variant: color of the active underline that slides under the selected tab.\n * @cssproperty [--indicator-thickness=2px] - `line` variant: thickness of the active underline.\n * @cssproperty [--track-color=var(--l-color-border)] - `line` variant: color of the static bottom border the tabs sit on.\n * @cssproperty [--track-thickness=1px] - `line` variant: thickness of the static bottom border.\n *\n * @customElement l-tabs\n */\nexport class Tabs extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n private _instanceId = uniqueId('tabs');\n private _tablistEl: HTMLElement | null = null;\n private _tabs: HTMLButtonElement[] = [];\n private _panels: HTMLElement[] = [];\n\n /** Visual variant. */\n @property({ reflect: true })\n variant: TabsVariant = 'line';\n\n /** Index of the active tab (0-based). */\n @property({ reflect: true })\n value = '0';\n\n /** Stretch tabs to fill container width. */\n @property({ type: Boolean, reflect: true, attribute: 'full-width' })\n fullWidth = false;\n\n /** Tab orientation. */\n @property({ reflect: true })\n orientation: TabsOrientation = 'horizontal';\n\n // --- Lifecycle ---\n\n override connectedCallback() {\n super.connectedCallback();\n // Defer setup to let light DOM children parse\n requestAnimationFrame(() => this._setup());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('value') && this._tabs.length) {\n this._selectTab(Number(this.value), false);\n }\n if (changed.has('orientation') && this._tablistEl) {\n this._tablistEl.setAttribute('aria-orientation', this.orientation);\n }\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n const children = Array.from(this.children) as HTMLElement[];\n if (children.length < 2) return;\n\n // First child is the tablist container\n this._tablistEl = children[0];\n this._tablistEl.setAttribute('role', 'tablist');\n this._tablistEl.setAttribute('aria-orientation', this.orientation);\n\n // Buttons inside tablist become tabs\n this._tabs = Array.from(this._tablistEl.querySelectorAll('button'));\n\n // Remaining children become panels\n this._panels = children.slice(1);\n\n const activeIndex = Number(this.value) || 0;\n\n // Enhance tabs\n for (let i = 0; i < this._tabs.length; i++) {\n const tab = this._tabs[i];\n const panel = this._panels[i];\n const name = tab.getAttribute('name') ?? String(i);\n const tabId = `${this._instanceId}-tab-${name}`;\n const panelId = `${this._instanceId}-panel-${name}`;\n\n tab.setAttribute('role', 'tab');\n tab.setAttribute('id', tabId);\n tab.setAttribute('aria-selected', String(i === activeIndex));\n tab.setAttribute('tabindex', i === activeIndex ? '0' : '-1');\n\n if (panel) {\n tab.setAttribute('aria-controls', panelId);\n panel.setAttribute('role', 'tabpanel');\n panel.setAttribute('id', panelId);\n panel.setAttribute('aria-labelledby', tabId);\n panel.setAttribute('tabindex', '0');\n if (i !== activeIndex) {\n panel.hidden = true;\n } else {\n panel.hidden = false;\n }\n }\n }\n\n // Attach listeners\n this._tablistEl.addEventListener('click', this._onClick);\n this._tablistEl.addEventListener('keydown', this._onKeyDown);\n\n // Initial indicator position\n requestAnimationFrame(() => this._updateIndicator());\n }\n\n private _teardown() {\n this._tablistEl?.removeEventListener('click', this._onClick);\n this._tablistEl?.removeEventListener('keydown', this._onKeyDown);\n }\n\n // --- Tab selection ---\n\n private _selectTab(index: number, emitEvent = true) {\n if (index < 0 || index >= this._tabs.length) return;\n\n for (let i = 0; i < this._tabs.length; i++) {\n const tab = this._tabs[i];\n const panel = this._panels[i];\n const isActive = i === index;\n\n tab.setAttribute('aria-selected', String(isActive));\n tab.setAttribute('tabindex', isActive ? '0' : '-1');\n\n if (panel) {\n panel.hidden = !isActive;\n }\n }\n\n this.value = String(index);\n this._updateIndicator();\n\n if (emitEvent) {\n const name = this._tabs[index]?.getAttribute('name') ?? null;\n this.emit('change', { detail: { index, name } });\n }\n }\n\n // --- Indicator ---\n\n private _updateIndicator() {\n if (!this._tablistEl) return;\n const activeTab = this._tabs[Number(this.value)];\n if (!activeTab) return;\n\n const isVertical = this.orientation === 'vertical';\n\n if (isVertical) {\n this._tablistEl.style.setProperty('--_indicator-top', `${activeTab.offsetTop}px`);\n this._tablistEl.style.setProperty('--_indicator-height', `${activeTab.offsetHeight}px`);\n } else {\n this._tablistEl.style.setProperty('--_indicator-left', `${activeTab.offsetLeft}px`);\n this._tablistEl.style.setProperty('--_indicator-width', `${activeTab.offsetWidth}px`);\n }\n }\n\n // --- Event handlers ---\n\n private _onClick = (e: Event) => {\n const tab = (e.target as HTMLElement).closest<HTMLButtonElement>('[role=\"tab\"]');\n if (!tab) return;\n const index = this._tabs.indexOf(tab);\n if (index >= 0) {\n this._selectTab(index);\n tab.focus();\n }\n };\n\n private _onKeyDown = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement;\n if (target.getAttribute('role') !== 'tab') return;\n\n const isHorizontal = this.orientation === 'horizontal';\n const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';\n const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';\n\n let index = this._tabs.indexOf(target as HTMLButtonElement);\n\n switch (e.key) {\n case nextKey:\n e.preventDefault();\n index = (index + 1) % this._tabs.length;\n this._selectTab(index);\n this._tabs[index].focus();\n break;\n case prevKey:\n e.preventDefault();\n index = (index - 1 + this._tabs.length) % this._tabs.length;\n this._selectTab(index);\n this._tabs[index].focus();\n break;\n case 'Home':\n e.preventDefault();\n this._selectTab(0);\n this._tabs[0].focus();\n break;\n case 'End':\n e.preventDefault();\n this._selectTab(this._tabs.length - 1);\n this._tabs[this._tabs.length - 1].focus();\n break;\n }\n };\n}\n"],"mappings":"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"}
|
package/cdn/standalone.css
CHANGED
|
@@ -3771,13 +3771,13 @@ In dark mode, mixes the base color with black (default 15% black).
|
|
|
3771
3771
|
|
|
3772
3772
|
l-tabs[variant='line'] {
|
|
3773
3773
|
& [role='tablist'] {
|
|
3774
|
-
border-bottom: 1px solid var(--l-color-border);
|
|
3774
|
+
border-bottom: var(--track-thickness, 1px) solid var(--track-color, var(--l-color-border));
|
|
3775
3775
|
gap: 0;
|
|
3776
3776
|
|
|
3777
3777
|
&::before {
|
|
3778
|
-
bottom: -1px;
|
|
3779
|
-
height: 2px;
|
|
3780
|
-
background: var(--l-color-text-primary);
|
|
3778
|
+
bottom: calc(-1 * var(--track-thickness, 1px));
|
|
3779
|
+
height: var(--indicator-thickness, 2px);
|
|
3780
|
+
background: var(--indicator-color, var(--l-color-text-primary));
|
|
3781
3781
|
border-radius: var(--l-radius-full);
|
|
3782
3782
|
}
|
|
3783
3783
|
}
|
package/cdn/standalone.js
CHANGED
|
@@ -5082,7 +5082,7 @@ __decorate([n$1({ attribute: "min-width" })], Dropdown.prototype, "minWidth", nu
|
|
|
5082
5082
|
define("dropdown", Dropdown);
|
|
5083
5083
|
//#endregion
|
|
5084
5084
|
//#region src/html/elements/dropdown-item/dropdown-item.ts
|
|
5085
|
-
var styles$10 = r$6(":host {\n display: block;\n}\n\n:host([disabled]) {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0.375rem 0.5rem;\n cursor: pointer;\n outline: none;\n border-radius: 4px;\n font-size: 0.875rem;\n line-height: 1.5;\n color: var(--l-color-text-primary, CanvasText);\n white-space: nowrap;\n text-align: start;\n}\n\n.item:focus-visible {\n background: var(--l-color-bg-state-hover);\n}\n\n@media (hover: hover) {\n .item:hover {\n background: var(--l-color-bg-state-hover);\n }\n}\n\n.check {\n display: flex;\n width: 16px;\n flex-shrink: 0;\n}\n\n:host(:not([checked])) .check svg {\n visibility: hidden;\n}\n\n::slotted([slot='prefix']),\n::slotted([slot='suffix']) {\n display: flex;\n flex-shrink: 0;\n}\n\n.label {\n flex: 1;\n}\n");
|
|
5085
|
+
var styles$10 = r$6(":host {\n display: block;\n}\n\n:host([disabled]) {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: 8px;\n box-sizing: border-box;\n min-block-size: 36px;\n padding: 0.375rem 0.5rem;\n cursor: pointer;\n outline: none;\n border-radius: 4px;\n font-size: 0.875rem;\n line-height: 1.5;\n color: var(--l-color-text-primary, CanvasText);\n white-space: nowrap;\n text-align: start;\n}\n\n.item:focus-visible {\n background: var(--l-color-bg-state-hover);\n}\n\n@media (hover: hover) {\n .item:hover {\n background: var(--l-color-bg-state-hover);\n }\n}\n\n.check {\n display: flex;\n width: 16px;\n flex-shrink: 0;\n}\n\n:host(:not([checked])) .check svg {\n visibility: hidden;\n}\n\n::slotted([slot='prefix']),\n::slotted([slot='suffix']) {\n display: flex;\n flex-shrink: 0;\n}\n\n.label {\n flex: 1;\n}\n");
|
|
5086
5086
|
/**
|
|
5087
5087
|
* A menu item for use inside `<l-dropdown>`.
|
|
5088
5088
|
*
|
|
@@ -31486,6 +31486,11 @@ define("sticky-bar", StickyBar);
|
|
|
31486
31486
|
*
|
|
31487
31487
|
* @event change - Fired when the active tab changes. Detail: `{ index: number, name: string | null }`.
|
|
31488
31488
|
*
|
|
31489
|
+
* @cssproperty [--indicator-color=var(--l-color-text-primary)] - `line` variant: color of the active underline that slides under the selected tab.
|
|
31490
|
+
* @cssproperty [--indicator-thickness=2px] - `line` variant: thickness of the active underline.
|
|
31491
|
+
* @cssproperty [--track-color=var(--l-color-border)] - `line` variant: color of the static bottom border the tabs sit on.
|
|
31492
|
+
* @cssproperty [--track-thickness=1px] - `line` variant: thickness of the static bottom border.
|
|
31493
|
+
*
|
|
31489
31494
|
* @customElement l-tabs
|
|
31490
31495
|
*/
|
|
31491
31496
|
var Tabs = class extends LuxenElement {
|