luxen-ui 0.9.3 → 0.10.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/cdn/chunks/picker.js +5 -0
- package/cdn/chunks/picker.js.map +1 -0
- package/cdn/custom-elements.json +145 -121
- package/cdn/elements/avatar/avatar.d.ts +1 -0
- package/cdn/elements/avatar/avatar.d.ts.map +1 -1
- package/cdn/elements/avatar/avatar.js +1 -1
- package/cdn/elements/avatar/avatar.js.map +1 -1
- package/cdn/elements/prose-editor/prose-editor.d.ts +39 -11
- package/cdn/elements/prose-editor/prose-editor.d.ts.map +1 -1
- package/cdn/elements/prose-editor/prose-editor.js +36 -36
- package/cdn/elements/prose-editor/prose-editor.js.map +1 -1
- package/cdn/standalone.js +1767 -4165
- package/cdn/standalone.js.map +1 -1
- package/dist/custom-elements.json +145 -121
- package/dist/elements/avatar/avatar.css +10 -10
- package/dist/elements/avatar/avatar.d.ts +1 -0
- package/dist/elements/avatar/avatar.d.ts.map +1 -1
- package/dist/elements/avatar/avatar.js +1 -0
- package/dist/elements/prose-editor/prose-editor.d.ts +39 -11
- package/dist/elements/prose-editor/prose-editor.d.ts.map +1 -1
- package/dist/elements/prose-editor/prose-editor.js +114 -38
- package/dist/metadata/avatar.json +5 -0
- package/dist/metadata/index.json +14 -1
- package/dist/metadata/prose-editor.json +8 -0
- package/dist/templates/elements/avatar.md +23 -0
- package/dist/templates/elements/prose-editor.md +11 -0
- package/package.json +2 -3
- package/cdn/chunks/module.js +0 -717
- package/cdn/chunks/module.js.map +0 -1
- package/cdn/chunks/native.js +0 -2
- package/cdn/chunks/native.js.map +0 -1
package/cdn/custom-elements.json
CHANGED
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
"description": "",
|
|
12
12
|
"name": "Avatar",
|
|
13
13
|
"cssProperties": [
|
|
14
|
+
{
|
|
15
|
+
"description": "Box size (any length). Set it inline (e.g. `style=\"--size: 20px\"`) for an arbitrary size beyond the `size` token scale; the font then follows proportionally. The `size` attribute sets it to the matching token.",
|
|
16
|
+
"name": "--size",
|
|
17
|
+
"default": "40px"
|
|
18
|
+
},
|
|
14
19
|
{
|
|
15
20
|
"description": "Background fill color for initials and the default icon.",
|
|
16
21
|
"name": "--color"
|
|
@@ -172,127 +177,6 @@
|
|
|
172
177
|
}
|
|
173
178
|
]
|
|
174
179
|
},
|
|
175
|
-
{
|
|
176
|
-
"kind": "javascript-module",
|
|
177
|
-
"path": "src/html/elements/badge/badge.ts",
|
|
178
|
-
"declarations": [
|
|
179
|
-
{
|
|
180
|
-
"kind": "class",
|
|
181
|
-
"description": "",
|
|
182
|
-
"name": "Badge",
|
|
183
|
-
"members": [
|
|
184
|
-
{
|
|
185
|
-
"kind": "field",
|
|
186
|
-
"name": "variant",
|
|
187
|
-
"type": {
|
|
188
|
-
"text": "BadgeVariant | undefined"
|
|
189
|
-
},
|
|
190
|
-
"description": "Style variant: `info`, `success`, `warning`, `danger`, or `neutral` (default)",
|
|
191
|
-
"attribute": "variant",
|
|
192
|
-
"reflects": true
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
"kind": "field",
|
|
196
|
-
"name": "pill",
|
|
197
|
-
"type": {
|
|
198
|
-
"text": "boolean"
|
|
199
|
-
},
|
|
200
|
-
"default": "false",
|
|
201
|
-
"description": "Display as pill shape",
|
|
202
|
-
"attribute": "pill",
|
|
203
|
-
"reflects": true
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
"kind": "field",
|
|
207
|
-
"name": "size",
|
|
208
|
-
"type": {
|
|
209
|
-
"text": "BadgeSize | undefined"
|
|
210
|
-
},
|
|
211
|
-
"description": "Badge size: `sm`, `lg`. Default is md.",
|
|
212
|
-
"attribute": "size",
|
|
213
|
-
"reflects": true
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
"kind": "field",
|
|
217
|
-
"name": "appearance",
|
|
218
|
-
"type": {
|
|
219
|
-
"text": "BadgeAppearance | undefined"
|
|
220
|
-
},
|
|
221
|
-
"description": "Visual appearance: `filled`, `filled-outlined`, `accent`. Default is outlined.",
|
|
222
|
-
"attribute": "appearance",
|
|
223
|
-
"reflects": true
|
|
224
|
-
}
|
|
225
|
-
],
|
|
226
|
-
"attributes": [
|
|
227
|
-
{
|
|
228
|
-
"name": "variant",
|
|
229
|
-
"type": {
|
|
230
|
-
"text": "BadgeVariant | undefined"
|
|
231
|
-
},
|
|
232
|
-
"description": "Style variant: `info`, `success`, `warning`, `danger`, or `neutral` (default)",
|
|
233
|
-
"fieldName": "variant"
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
"name": "pill",
|
|
237
|
-
"type": {
|
|
238
|
-
"text": "boolean"
|
|
239
|
-
},
|
|
240
|
-
"default": "false",
|
|
241
|
-
"description": "Display as pill shape",
|
|
242
|
-
"fieldName": "pill"
|
|
243
|
-
},
|
|
244
|
-
{
|
|
245
|
-
"name": "size",
|
|
246
|
-
"type": {
|
|
247
|
-
"text": "BadgeSize | undefined"
|
|
248
|
-
},
|
|
249
|
-
"description": "Badge size: `sm`, `lg`. Default is md.",
|
|
250
|
-
"fieldName": "size"
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
"name": "appearance",
|
|
254
|
-
"type": {
|
|
255
|
-
"text": "BadgeAppearance | undefined"
|
|
256
|
-
},
|
|
257
|
-
"description": "Visual appearance: `filled`, `filled-outlined`, `accent`. Default is outlined.",
|
|
258
|
-
"fieldName": "appearance"
|
|
259
|
-
}
|
|
260
|
-
],
|
|
261
|
-
"superclass": {
|
|
262
|
-
"name": "LuxenElement",
|
|
263
|
-
"module": "/src/html/shared/luxen-element.js"
|
|
264
|
-
},
|
|
265
|
-
"tagName": "l-badge",
|
|
266
|
-
"customElement": true,
|
|
267
|
-
"summary": "A badge component for displaying small status indicators."
|
|
268
|
-
}
|
|
269
|
-
],
|
|
270
|
-
"exports": [
|
|
271
|
-
{
|
|
272
|
-
"kind": "js",
|
|
273
|
-
"name": "Badge",
|
|
274
|
-
"declaration": {
|
|
275
|
-
"name": "Badge",
|
|
276
|
-
"module": "src/html/elements/badge/badge.ts"
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
]
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
"kind": "javascript-module",
|
|
283
|
-
"path": "src/html/elements/badge/index.ts",
|
|
284
|
-
"declarations": [],
|
|
285
|
-
"exports": [
|
|
286
|
-
{
|
|
287
|
-
"kind": "js",
|
|
288
|
-
"name": "*",
|
|
289
|
-
"declaration": {
|
|
290
|
-
"name": "*",
|
|
291
|
-
"module": "src/html/elements/badge/badge.js"
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
]
|
|
295
|
-
},
|
|
296
180
|
{
|
|
297
181
|
"kind": "javascript-module",
|
|
298
182
|
"path": "src/html/elements/button/button.meta.ts",
|
|
@@ -446,6 +330,127 @@
|
|
|
446
330
|
}
|
|
447
331
|
]
|
|
448
332
|
},
|
|
333
|
+
{
|
|
334
|
+
"kind": "javascript-module",
|
|
335
|
+
"path": "src/html/elements/badge/badge.ts",
|
|
336
|
+
"declarations": [
|
|
337
|
+
{
|
|
338
|
+
"kind": "class",
|
|
339
|
+
"description": "",
|
|
340
|
+
"name": "Badge",
|
|
341
|
+
"members": [
|
|
342
|
+
{
|
|
343
|
+
"kind": "field",
|
|
344
|
+
"name": "variant",
|
|
345
|
+
"type": {
|
|
346
|
+
"text": "BadgeVariant | undefined"
|
|
347
|
+
},
|
|
348
|
+
"description": "Style variant: `info`, `success`, `warning`, `danger`, or `neutral` (default)",
|
|
349
|
+
"attribute": "variant",
|
|
350
|
+
"reflects": true
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"kind": "field",
|
|
354
|
+
"name": "pill",
|
|
355
|
+
"type": {
|
|
356
|
+
"text": "boolean"
|
|
357
|
+
},
|
|
358
|
+
"default": "false",
|
|
359
|
+
"description": "Display as pill shape",
|
|
360
|
+
"attribute": "pill",
|
|
361
|
+
"reflects": true
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"kind": "field",
|
|
365
|
+
"name": "size",
|
|
366
|
+
"type": {
|
|
367
|
+
"text": "BadgeSize | undefined"
|
|
368
|
+
},
|
|
369
|
+
"description": "Badge size: `sm`, `lg`. Default is md.",
|
|
370
|
+
"attribute": "size",
|
|
371
|
+
"reflects": true
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"kind": "field",
|
|
375
|
+
"name": "appearance",
|
|
376
|
+
"type": {
|
|
377
|
+
"text": "BadgeAppearance | undefined"
|
|
378
|
+
},
|
|
379
|
+
"description": "Visual appearance: `filled`, `filled-outlined`, `accent`. Default is outlined.",
|
|
380
|
+
"attribute": "appearance",
|
|
381
|
+
"reflects": true
|
|
382
|
+
}
|
|
383
|
+
],
|
|
384
|
+
"attributes": [
|
|
385
|
+
{
|
|
386
|
+
"name": "variant",
|
|
387
|
+
"type": {
|
|
388
|
+
"text": "BadgeVariant | undefined"
|
|
389
|
+
},
|
|
390
|
+
"description": "Style variant: `info`, `success`, `warning`, `danger`, or `neutral` (default)",
|
|
391
|
+
"fieldName": "variant"
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"name": "pill",
|
|
395
|
+
"type": {
|
|
396
|
+
"text": "boolean"
|
|
397
|
+
},
|
|
398
|
+
"default": "false",
|
|
399
|
+
"description": "Display as pill shape",
|
|
400
|
+
"fieldName": "pill"
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"name": "size",
|
|
404
|
+
"type": {
|
|
405
|
+
"text": "BadgeSize | undefined"
|
|
406
|
+
},
|
|
407
|
+
"description": "Badge size: `sm`, `lg`. Default is md.",
|
|
408
|
+
"fieldName": "size"
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
"name": "appearance",
|
|
412
|
+
"type": {
|
|
413
|
+
"text": "BadgeAppearance | undefined"
|
|
414
|
+
},
|
|
415
|
+
"description": "Visual appearance: `filled`, `filled-outlined`, `accent`. Default is outlined.",
|
|
416
|
+
"fieldName": "appearance"
|
|
417
|
+
}
|
|
418
|
+
],
|
|
419
|
+
"superclass": {
|
|
420
|
+
"name": "LuxenElement",
|
|
421
|
+
"module": "/src/html/shared/luxen-element.js"
|
|
422
|
+
},
|
|
423
|
+
"tagName": "l-badge",
|
|
424
|
+
"customElement": true,
|
|
425
|
+
"summary": "A badge component for displaying small status indicators."
|
|
426
|
+
}
|
|
427
|
+
],
|
|
428
|
+
"exports": [
|
|
429
|
+
{
|
|
430
|
+
"kind": "js",
|
|
431
|
+
"name": "Badge",
|
|
432
|
+
"declaration": {
|
|
433
|
+
"name": "Badge",
|
|
434
|
+
"module": "src/html/elements/badge/badge.ts"
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
]
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
"kind": "javascript-module",
|
|
441
|
+
"path": "src/html/elements/badge/index.ts",
|
|
442
|
+
"declarations": [],
|
|
443
|
+
"exports": [
|
|
444
|
+
{
|
|
445
|
+
"kind": "js",
|
|
446
|
+
"name": "*",
|
|
447
|
+
"declaration": {
|
|
448
|
+
"name": "*",
|
|
449
|
+
"module": "src/html/elements/badge/badge.js"
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
]
|
|
453
|
+
},
|
|
449
454
|
{
|
|
450
455
|
"kind": "javascript-module",
|
|
451
456
|
"path": "src/html/elements/button-group/button-group.ts",
|
|
@@ -3803,6 +3808,16 @@
|
|
|
3803
3808
|
"description": "Placeholder shown when the editor is empty.",
|
|
3804
3809
|
"attribute": "placeholder"
|
|
3805
3810
|
},
|
|
3811
|
+
{
|
|
3812
|
+
"kind": "field",
|
|
3813
|
+
"name": "emojiDataSource",
|
|
3814
|
+
"type": {
|
|
3815
|
+
"text": "string"
|
|
3816
|
+
},
|
|
3817
|
+
"default": "''",
|
|
3818
|
+
"description": "URL the emoji picker fetches its data from. Point this at a locally served\n`emojibase-data` JSON to run fully offline (no CDN). Defaults to the\npicker's bundled CDN source.",
|
|
3819
|
+
"attribute": "emoji-data-source"
|
|
3820
|
+
},
|
|
3806
3821
|
{
|
|
3807
3822
|
"kind": "field",
|
|
3808
3823
|
"name": "validationTarget",
|
|
@@ -3997,6 +4012,15 @@
|
|
|
3997
4012
|
"default": "''",
|
|
3998
4013
|
"description": "Placeholder shown when the editor is empty.",
|
|
3999
4014
|
"fieldName": "placeholder"
|
|
4015
|
+
},
|
|
4016
|
+
{
|
|
4017
|
+
"name": "emoji-data-source",
|
|
4018
|
+
"type": {
|
|
4019
|
+
"text": "string"
|
|
4020
|
+
},
|
|
4021
|
+
"default": "''",
|
|
4022
|
+
"description": "URL the emoji picker fetches its data from. Point this at a locally served\n`emojibase-data` JSON to run fully offline (no CDN). Defaults to the\npicker's bundled CDN source.",
|
|
4023
|
+
"fieldName": "emojiDataSource"
|
|
4000
4024
|
}
|
|
4001
4025
|
],
|
|
4002
4026
|
"superclass": {
|
|
@@ -3,6 +3,7 @@ import { LuxenElement } from '../../shared/luxen-element.js';
|
|
|
3
3
|
* @summary An avatar component for displaying user images, initials, or a default icon.
|
|
4
4
|
* @customElement l-avatar
|
|
5
5
|
*
|
|
6
|
+
* @cssproperty [--size=40px] - Box size (any length). Set it inline (e.g. `style="--size: 20px"`) for an arbitrary size beyond the `size` token scale; the font then follows proportionally. The `size` attribute sets it to the matching token.
|
|
6
7
|
* @cssproperty --color - Background fill color for initials and the default icon.
|
|
7
8
|
* @cssproperty --text-color - Initials/icon color over `--color`. Defaults to an auto-derived readable color; set it to enforce a specific brand color (overrides the automatic choice).
|
|
8
9
|
* @cssproperty --appearance - Set to `circle` for a fully circular avatar (default is a rounded square).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../../src/html/elements/avatar/avatar.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAqB7D
|
|
1
|
+
{"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../../src/html/elements/avatar/avatar.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAqB7D;;;;;;;;;;;;GAYG;AACH,qBAAa,MAAO,SAAQ,YAAY;IACtC,MAAM,CAAC,MAAM,4BAAwB;IAErC,qFAAqF;IAErF,GAAG,SAAM;IAET,6EAA6E;IAE7E,IAAI,SAAM;IAEV,8DAA8D;IAE9D,IAAI,SAAQ;IAEZ,4DAA4D;IAE5D,KAAK,SAAK;IAEV,+DAA+D;IAE/D,WAAW,UAAS;IAEX,OAAO,CAAC,SAAS,CAAS;IAEnC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAMxC,iBAAiB;IAOjB,OAAO;IASP,OAAO,KAAK,IAAI,GAEf;IAED,MAAM;IA6BN,OAAO,CAAC,QAAQ,CAEd;CACH"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e}from"../../chunks/lit.js";import{a as t,o as n,t as r}from"../../chunks/lit-html.js";import{LuxenElement as i}from"../../shared/luxen-element.js";import{r as a,t as o}from"../../chunks/static-html.js";import{i as s,r as c,t as l}from"../../chunks/decorate.js";import u from"../../shared/styles/host.styles.js";var d=e(`:host{--
|
|
1
|
+
import{i as e}from"../../chunks/lit.js";import{a as t,o as n,t as r}from"../../chunks/lit-html.js";import{LuxenElement as i}from"../../shared/luxen-element.js";import{r as a,t as o}from"../../chunks/static-html.js";import{i as s,r as c,t as l}from"../../chunks/decorate.js";import u from"../../shared/styles/host.styles.js";var d=e(`:host{--size:40px;--_font-size:calc(var(--size) * .4);width:var(--size);height:var(--size);border-radius:calc(var(--size) * .15);isolation:isolate;vertical-align:middle;color:var(--l-color-text-secondary);flex-shrink:0;justify-content:center;align-items:center;display:inline-flex;position:relative}:host([size=xs]){--size:24px;--_font-size:.75rem}:host([size=sm]){--size:32px;--_font-size:.875rem}:host([size=lg]){--size:48px;--_font-size:1.25rem}:host([size=xl]){--size:56px;--_font-size:1.25rem}img{object-fit:cover;border-radius:inherit;width:100%;height:100%}.initials{margin:auto}.icon{color:currentColor;width:60%;height:60%}.badge{z-index:1;min-width:12px;height:12px;box-shadow:0 0 0 2px var(--l-color-surface);background-color:var(--l-color-surface);font-variant-numeric:tabular-nums;color:var(--l-color-text-primary);border-radius:3px;justify-content:center;align-items:center;padding-inline:2px;font-size:.625rem;font-weight:500;line-height:1;display:flex;position:absolute;bottom:0;right:0;overflow:hidden}.base:after{content:"";border-radius:inherit;pointer-events:none;position:absolute;inset:0;box-shadow:inset 0 0 0 1px var(--lightningcss-light,oklch(0% 0 0/.07))var(--lightningcss-dark,oklch(100% 0 0/.1))}.base{border-radius:calc(var(--size) * .15);background-color:var(--color,var(--l-color-bg-fill-neutral-soft));--_on:calc(255 * ( 1 - sign(.2126 * (r / 255) * (r / 255) + .7152 * (g / 255) * (g / 255) + .0722 * (b / 255) * (b / 255) - .2) ) / 2);width:100%;height:100%;color:var(--text-color,rgb(from var(--color) var(--_on) var(--_on) var(--_on)));font-size:var(--_font-size);text-transform:uppercase;cursor:inherit;border:none;justify-content:center;align-items:center;padding:0;font-weight:500;line-height:1;display:inline-flex}@supports (color:contrast-color(red)){.base{color:var(--text-color,contrast-color(var(--color)))}}button.base{cursor:pointer}button.base:focus-visible{outline:2px solid var(--l-focus-ring);outline-offset:2px}button.base:hover{box-shadow:inset 0 0 0 1.5px var(--l-color-border-interactive)}@container style(--appearance:circle){.base{border-radius:50%}}`);function f(e){return e.match(/(\b\S)?/g).join(``).match(/(^\S|\S$)?/g).join(``).toUpperCase()}var p=n`<svg class="icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
2
2
|
<path d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z" />
|
|
3
3
|
</svg>`,m=class extends i{constructor(...e){super(...e),this.src=``,this.name=``,this.size=`md`,this.badge=0,this.interactive=!1,this._hasError=!1,this._onError=()=>{this._hasError=!0}}static{this.styles=[u,d]}willUpdate(e){e.has(`src`)&&(this._hasError=!1)}connectedCallback(){super.connectedCallback(),this.hasAttribute(`role`)||this.setAttribute(`role`,`img`)}updated(){this.name&&this.setAttribute(`aria-label`,this.name);let e=getComputedStyle(this).getPropertyValue(`--appearance`).trim()===`circle`;this.style.borderRadius=e?`50%`:``}get _tag(){return this.interactive?o`button`:o`div`}render(){let e=this.src&&!this._hasError?t`<img
|
|
4
4
|
src=${this.src}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar.js","names":[],"sources":["../../../src/html/elements/avatar/avatar.css?inline","../../../src/html/elements/avatar/avatar.ts"],"sourcesContent":[":host {\n --
|
|
1
|
+
{"version":3,"file":"avatar.js","names":[],"sources":["../../../src/html/elements/avatar/avatar.css?inline","../../../src/html/elements/avatar/avatar.ts"],"sourcesContent":[":host {\n --size: 40px;\n --_font-size: calc(var(--size) * 0.4);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n width: var(--size);\n height: var(--size);\n border-radius: calc(var(--size) * 0.15);\n isolation: isolate;\n vertical-align: middle;\n flex-shrink: 0;\n color: var(--l-color-text-secondary);\n}\n\n:host([size='xs']) {\n --size: 24px;\n --_font-size: 0.75rem;\n}\n:host([size='sm']) {\n --size: 32px;\n --_font-size: 0.875rem;\n}\n:host([size='lg']) {\n --size: 48px;\n --_font-size: 1.25rem;\n}\n:host([size='xl']) {\n --size: 56px;\n --_font-size: 1.25rem;\n}\n\nimg {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: inherit;\n}\n\n.initials {\n margin: auto;\n}\n\n.icon {\n width: 60%;\n height: 60%;\n color: currentColor;\n}\n\n.badge {\n position: absolute;\n bottom: 0;\n right: 0;\n z-index: 1;\n height: 12px;\n min-width: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding-inline: 2px;\n border-radius: 3px;\n box-shadow: 0 0 0 2px var(--l-color-surface);\n background-color: var(--l-color-surface);\n font-size: 0.625rem;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n line-height: 1;\n color: var(--l-color-text-primary);\n overflow: hidden;\n}\n\n/*\n * Inset ring via ::after so it renders on top of the <img>.\n * A box-shadow on :host would be covered by the image since\n * it fills the entire element with object-fit: cover.\n */\n.base::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n box-shadow: inset 0 0 0 1px light-dark(oklch(0 0 0 / 7%), oklch(100% 0 0 / 10%));\n pointer-events: none;\n}\n\n.base {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n border: none;\n border-radius: calc(var(--size) * 0.15);\n background-color: var(--color, var(--l-color-bg-fill-neutral-soft));\n /*\n * Text over --color, decided by the background's own luminance — never the\n * document mode, since --color is consumer-set and ignores light/dark.\n * The contrast-color() block below is the primary path (Baseline 2026); this\n * --_on calc() is the fallback for browsers predating it (Chrome ≤146,\n * Safari <26, Firefox <146). It approximates WCAG relative luminance with\n * squared sRGB channels (a cheap linearization, Rec. 709 weights) and flips at\n * 0.2, just above the black/white crossover (~0.179) to offset squaring\n * underestimating mid-tones — holding AA across saturated brand colors where an\n * OKLCH-lightness threshold collapses to ≈1:1 (OKLCH L tracks hue, not\n * luminance: a mid red reads \"light\" yet needs white text). --text-color lets\n * consumers force a specific brand text color, overriding both paths.\n */\n --_on: calc(\n 255 *\n (\n 1 -\n sign(\n 0.2126 * (r / 255) * (r / 255) + 0.7152 * (g / 255) * (g / 255) + 0.0722 * (b / 255) *\n (b / 255) - 0.2\n )\n ) /\n 2\n );\n color: var(--text-color, rgb(from var(--color) var(--_on) var(--_on) var(--_on)));\n font-size: var(--_font-size);\n font-weight: 500;\n line-height: 1;\n text-transform: uppercase;\n padding: 0;\n cursor: inherit;\n}\n\n/* Primary path: native, guaranteed-contrast black/white. contrast-color() is\n * Baseline Newly Available (2026) — Safari 26+, Firefox 146+, Chrome/Edge 147+ —\n * and supersedes the luminance approximation above where supported. @supports (not\n * declaration order) is required: the value contains var(), so a non-supporting\n * browser would treat contrast-color() as invalid-at-computed-value-time and reset\n * to `inherit` rather than falling back to the calc() line. No bg fallback inside,\n * so a bare avatar (no --color) keeps inheriting --l-color-text-secondary.\n * --text-color still wins here, overriding contrast-color()'s choice.\n * (The earlier `… vs black, white to AA` extended syntax was dropped from the spec.) */\n@supports (color: contrast-color(red)) {\n .base {\n color: var(--text-color, contrast-color(var(--color)));\n }\n}\n\nbutton.base {\n cursor: pointer;\n}\n\nbutton.base:focus-visible {\n outline: 2px solid var(--l-focus-ring);\n outline-offset: 2px;\n}\n\nbutton.base:hover {\n box-shadow: inset 0 0 0 1.5px var(--l-color-border-interactive);\n}\n\n@container style(--appearance: circle) {\n .base {\n border-radius: 50%;\n }\n}\n","import { html, nothing, svg, unsafeCSS } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { html as staticHtml, literal } from 'lit/static-html.js';\nimport { property, state } from 'lit/decorators.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './avatar.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\nfunction getInitials(name: string): string {\n return name\n .match(/(\\b\\S)?/g)!\n .join('')\n .match(/(^\\S|\\S$)?/g)!\n .join('')\n .toUpperCase();\n}\n\nconst defaultIcon = svg`<svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z\" />\n</svg>`;\n\n/**\n * @summary An avatar component for displaying user images, initials, or a default icon.\n * @customElement l-avatar\n *\n * @cssproperty [--size=40px] - Box size (any length). Set it inline (e.g. `style=\"--size: 20px\"`) for an arbitrary size beyond the `size` token scale; the font then follows proportionally. The `size` attribute sets it to the matching token.\n * @cssproperty --color - Background fill color for initials and the default icon.\n * @cssproperty --text-color - Initials/icon color over `--color`. Defaults to an auto-derived readable color; set it to enforce a specific brand color (overrides the automatic choice).\n * @cssproperty --appearance - Set to `circle` for a fully circular avatar (default is a rounded square).\n *\n * @csspart base - The avatar container that paints `--color`; style it (e.g. `color`) to override the auto-derived text color.\n *\n * @cssClass .l-avatar-group - Flex wrapper that overlaps a row of stacked avatars.\n */\nexport class Avatar extends LuxenElement {\n static styles = [hostStyles, styles];\n\n /** Image URL. Falls back to initials (then the default icon) if it fails to load. */\n @property()\n src = '';\n\n /** Name used as the accessible label and to derive the initials fallback. */\n @property()\n name = '';\n\n /** Avatar size: `xs`, `sm`, `md` (default), `lg`, or `xl`. */\n @property({ reflect: true })\n size = 'md';\n\n /** Count shown in the corner badge. `0` hides the badge. */\n @property({ type: Number })\n badge = 0;\n\n /** Render as a `<button>` with focus ring and hover states. */\n @property({ type: Boolean, reflect: true })\n interactive = false;\n\n @state() private _hasError = false;\n\n willUpdate(changed: Map<string, unknown>) {\n if (changed.has('src')) {\n this._hasError = false;\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'img');\n }\n }\n\n updated() {\n if (this.name) {\n this.setAttribute('aria-label', this.name);\n }\n\n const isCircle = getComputedStyle(this).getPropertyValue('--appearance').trim() === 'circle';\n this.style.borderRadius = isCircle ? '50%' : '';\n }\n\n private get _tag() {\n return this.interactive ? literal`button` : literal`div`;\n }\n\n render() {\n const content =\n this.src && !this._hasError\n ? html`<img\n src=${this.src}\n alt=${this.name || ''}\n @error=${this._onError}\n />`\n : this.name\n ? html`<span class=\"initials\">${getInitials(this.name)}</span>`\n : html`<slot>${defaultIcon}</slot>`;\n\n return staticHtml`\n <${this._tag} class=\"base\" part=\"base\" type=${this.interactive ? 'button' : nothing}>\n ${content}\n </${this._tag}>\n ${\n this.badge\n ? html`<div\n class=\"badge\"\n aria-hidden=\"true\"\n >\n ${this.badge}\n </div>`\n : nothing\n }\n `;\n }\n\n private _onError = () => {\n this._hasError = true;\n };\n}\n"],"mappings":"oUCOA,IAAM,EAAS,EAAU,6jEAAU,CAEnC,SAAS,EAAY,EAAsB,CACzC,OAAO,EACJ,MAAM,WAAW,CACjB,KAAK,GAAG,CACR,MAAM,cAAc,CACpB,KAAK,GAAG,CACR,aAAa,CAGlB,IAAM,EAAc,CAAG;;QAiBV,EAAb,cAA4B,CAAa,wCAKjC,aAIC,aAIA,gBAIC,mBAIM,kBAEe,qBAyDJ,CACvB,KAAK,UAAY,uBAhFH,CAAC,EAAY,EAAO,CAwBpC,WAAW,EAA+B,CACpC,EAAQ,IAAI,MAAM,GACpB,KAAK,UAAY,IAIrB,mBAAoB,CAClB,MAAM,mBAAmB,CACpB,KAAK,aAAa,OAAO,EAC5B,KAAK,aAAa,OAAQ,MAAM,CAIpC,SAAU,CACJ,KAAK,MACP,KAAK,aAAa,aAAc,KAAK,KAAK,CAG5C,IAAM,EAAW,iBAAiB,KAAK,CAAC,iBAAiB,eAAe,CAAC,MAAM,GAAK,SACpF,KAAK,MAAM,aAAe,EAAW,MAAQ,GAG/C,IAAY,MAAO,CACjB,OAAO,KAAK,YAAc,CAAO,SAAW,CAAO,MAGrD,QAAS,CACP,IAAM,EACJ,KAAK,KAAO,CAAC,KAAK,UACd,CAAI;kBACI,KAAK,IAAI;kBACT,KAAK,MAAQ,GAAG;qBACb,KAAK,SAAS;cAEzB,KAAK,KACH,CAAI,0BAA0B,EAAY,KAAK,KAAK,CAAC,SACrD,CAAI,SAAS,EAAY,SAEjC,MAAO,EAAU;SACZ,KAAK,KAAK,iCAAiC,KAAK,YAAc,SAAW,EAAQ;UAChF,EAAQ;UACR,KAAK,KAAK;QAEZ,KAAK,MACD,CAAI;;;;gBAIA,KAAK,MAAM;oBAEf,EACL;WAxEJ,GAAU,CAAA,CAAA,EAAA,UAAA,MAAA,IAAA,GAAA,IAIV,GAAU,CAAA,CAAA,EAAA,UAAA,OAAA,IAAA,GAAA,IAIV,EAAS,CAAE,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,OAAA,IAAA,GAAA,IAI3B,EAAS,CAAE,KAAM,OAAQ,CAAC,CAAA,CAAA,EAAA,UAAA,QAAA,IAAA,GAAA,IAI1B,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,cAAA,IAAA,GAAA,IAG1C,GAAO,CAAA,CAAA,EAAA,UAAA,YAAA,IAAA,GAAA"}
|
|
@@ -57,10 +57,17 @@ export declare class ProseEditor extends LuxenFormAssociatedElement {
|
|
|
57
57
|
accessor autofocus: boolean;
|
|
58
58
|
/** Placeholder shown when the editor is empty. */
|
|
59
59
|
accessor placeholder: string;
|
|
60
|
+
/**
|
|
61
|
+
* URL the emoji picker fetches its data from. Point this at a locally served
|
|
62
|
+
* `emojibase-data` JSON to run fully offline (no CDN). Defaults to the
|
|
63
|
+
* picker's bundled CDN source.
|
|
64
|
+
*/
|
|
65
|
+
accessor emojiDataSource: string;
|
|
60
66
|
private _editorRoot?;
|
|
61
67
|
private _emojiPicker?;
|
|
62
68
|
private _emojiPickerPromise?;
|
|
63
69
|
private _emojiOpenAtPointerDown;
|
|
70
|
+
private _emojiAutoUpdateCleanup?;
|
|
64
71
|
get validationTarget(): HTMLElement | undefined;
|
|
65
72
|
private get _toolbar();
|
|
66
73
|
firstUpdated(): void;
|
|
@@ -104,23 +111,34 @@ export declare class ProseEditor extends LuxenFormAssociatedElement {
|
|
|
104
111
|
private _onFocus;
|
|
105
112
|
private _onKeyDown;
|
|
106
113
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
114
|
+
* Capture-phase outside-click dismissal — the robust fallback the platform's
|
|
115
|
+
* native light-dismiss can't be trusted to provide (see `firstUpdated`).
|
|
116
|
+
* Dismiss when the picker is open and the pointer landed on neither the
|
|
117
|
+
* picker nor the emoji toolbar button (re-clicking the button is handled by
|
|
118
|
+
* the toggle in `_onEmojiButtonClick`). `composedPath()` crosses shadow
|
|
119
|
+
* boundaries, so a click inside the picker's shadow tree still resolves to
|
|
120
|
+
* the host element here.
|
|
121
|
+
*/
|
|
122
|
+
private _onDocumentPointerDown;
|
|
123
|
+
/**
|
|
124
|
+
* The picker is a `popover="auto"` parented into the top layer; outside-click
|
|
125
|
+
* dismissal is owned by `_onDocumentPointerDown` (capture phase), which
|
|
126
|
+
* survives `stopPropagation()`/`preventDefault()` from an ancestor (modal
|
|
127
|
+
* `<l-dialog>`, ProseMirror, Vue delegation). (`Escape` is handled by
|
|
128
|
+
* `_onKeyDown` instead — ProseMirror `preventDefault()`s it, which would
|
|
129
|
+
* cancel the native close.)
|
|
113
130
|
*
|
|
114
131
|
* We can't wire the button as a native popover invoker (`popoverTargetElement`
|
|
115
132
|
* / `popovertarget`) because the picker is parented into another shadow tree
|
|
116
133
|
* (the open `<dialog>` — see `_topLayerContainer`) while the button lives in
|
|
117
134
|
* this element's shadow root; a cross-tree invoker reference doesn't resolve.
|
|
118
135
|
* So the toggle is hand-rolled here. The catch: a pointer click on the button
|
|
119
|
-
* is "outside" the popover, so native light-dismiss
|
|
120
|
-
* picker by the time this `click` fires (light-dismiss
|
|
121
|
-
* We therefore read the open state captured at
|
|
122
|
-
* this click should re-open or stay closed.
|
|
123
|
-
* has no pointer light-dismiss, so it
|
|
136
|
+
* is "outside" the popover, so native light-dismiss (where it works) has
|
|
137
|
+
* already closed an open picker by the time this `click` fires (light-dismiss
|
|
138
|
+
* runs on `pointerup`). We therefore read the open state captured at
|
|
139
|
+
* `pointerdown` to know whether this click should re-open or stay closed.
|
|
140
|
+
* Keyboard activation (`detail === 0`) has no pointer light-dismiss, so it
|
|
141
|
+
* reads the live state and toggles directly.
|
|
124
142
|
*/
|
|
125
143
|
private _onEmojiButtonPointerDown;
|
|
126
144
|
private _onEmojiButtonClick;
|
|
@@ -134,6 +152,16 @@ export declare class ProseEditor extends LuxenFormAssociatedElement {
|
|
|
134
152
|
*/
|
|
135
153
|
private _topLayerContainer;
|
|
136
154
|
private get _emojiButton();
|
|
155
|
+
/**
|
|
156
|
+
* Keep the picker pinned to the emoji button while it is open. Floating UI's
|
|
157
|
+
* `autoUpdate` re-runs `_positionEmojiPicker` on scroll (including ancestor
|
|
158
|
+
* scroll), resize, and layout shifts, so the picker stays anchored to the
|
|
159
|
+
* button — the cross-tree equivalent of CSS anchor positioning, which can't be
|
|
160
|
+
* used here because the button lives in this element's shadow root while the
|
|
161
|
+
* picker is parented to the top-layer container (a different tree scope).
|
|
162
|
+
*/
|
|
163
|
+
private _startEmojiAutoUpdate;
|
|
164
|
+
private _stopEmojiAutoUpdate;
|
|
137
165
|
private _positionEmojiPicker;
|
|
138
166
|
private _renderButton;
|
|
139
167
|
private _renderToolbarItem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prose-editor.d.ts","sourceRoot":"","sources":["../../../src/html/elements/prose-editor/prose-editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAO1E,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAIxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAE3F,OAAO,kBAAkB,CAAC;AAK1B,KAAK,kBAAkB,GACnB,WAAW,GACX,WAAW,GACX,WAAW,GACX,MAAM,GACN,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,iBAAiB,GACjB,MAAM,GACN,OAAO,GACP,YAAY,GACZ,MAAM,GACN,MAAM,GACN,SAAS,CAAC;AA2Bd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,WAAY,SAAQ,0BAA0B;IACzD,OAAgB,MAAM,4BAAwB;IAE9C,oEAAoE;IACpE,MAAM,EAAG,MAAM,CAAC;IAEhB,4BAA4B;IAE5B,QAAQ,CAAC,WAAW,SAAM;IAE1B,+DAA+D;IAE/D,QAAQ,CAAC,WAAW,SAAM;IAE1B,mGAAmG;IAEnG,QAAQ,CAAC,WAAW,SAAW;IAE/B,8EAA8E;IAO9E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,EAAE,CAAM;IAE5C,8DAA8D;IAE9D,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,SAAS,CAAa;IAE1D,sDAAsD;IAEtD,QAAQ,CAAC,gBAAgB,EAAE,KAAK,GAAG,QAAQ,CAAS;IAEpD,oCAAoC;IAEpC,QAAQ,CAAC,SAAS,UAAS;IAE3B,kDAAkD;IAElD,QAAQ,CAAC,WAAW,SAAM;IAE1B,OAAO,CAAC,WAAW,CAAC,CAAiB;IACrC,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,mBAAmB,CAAC,CAAuB;IACnD,OAAO,CAAC,uBAAuB,CAAS;
|
|
1
|
+
{"version":3,"file":"prose-editor.d.ts","sourceRoot":"","sources":["../../../src/html/elements/prose-editor/prose-editor.ts"],"names":[],"mappings":"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"}
|