@greypan/web-ui 7.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.CN.md +109 -24
- package/README.md +149 -63
- package/dist/assets/menu-portal.js +1 -1
- package/dist/assets/menu-portal.js.map +1 -1
- package/dist/assets/selection-control.js +1 -1
- package/dist/assets/selection-control.js.map +1 -1
- package/dist/components/autocomplete/index.d.ts +17 -5
- package/dist/components/autocomplete/index.js +138 -103
- package/dist/components/autocomplete/index.js.map +1 -1
- package/dist/components/autocomplete/style.js +1 -1
- package/dist/components/autocomplete/style.js.map +1 -1
- package/dist/components/avatar/index.js +4 -4
- package/dist/components/badge/style.js.map +1 -1
- package/dist/components/button/index.d.ts +368 -1
- package/dist/components/button/index.js +61 -41
- package/dist/components/button/index.js.map +1 -1
- package/dist/components/button/style.js +1 -1
- package/dist/components/button/style.js.map +1 -1
- package/dist/components/button-group/index.js +5 -5
- package/dist/components/checkbox/index.d.ts +3 -0
- package/dist/components/checkbox/index.js +30 -32
- package/dist/components/checkbox/index.js.map +1 -1
- package/dist/components/checkbox/style.js +1 -1
- package/dist/components/checkbox/style.js.map +1 -1
- package/dist/components/checkbox-group/index.js +4 -4
- package/dist/components/context-menu/index.js +4 -1
- package/dist/components/context-menu/index.js.map +1 -1
- package/dist/components/dialog/index.js +11 -8
- package/dist/components/dialog/index.js.map +1 -1
- package/dist/components/drawer/index.js +11 -8
- package/dist/components/drawer/index.js.map +1 -1
- package/dist/components/dropdown/index.js +4 -1
- package/dist/components/dropdown/index.js.map +1 -1
- package/dist/components/dropdown-item/style.js +1 -1
- package/dist/components/dropdown-item/style.js.map +1 -1
- package/dist/components/editable-text/index.d.ts +473 -0
- package/dist/components/editable-text/index.js +226 -0
- package/dist/components/editable-text/index.js.map +1 -0
- package/dist/components/editable-text/style.js +6 -0
- package/dist/components/editable-text/style.js.map +1 -0
- package/dist/components/icon/index.js +7 -7
- package/dist/components/icon/index.js.map +1 -1
- package/dist/components/image-preview/index.js +21 -18
- package/dist/components/image-preview/index.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +39 -38
- package/dist/components/input/index.d.ts +9 -0
- package/dist/components/input/index.js +41 -30
- package/dist/components/input/index.js.map +1 -1
- package/dist/components/input-number/index.d.ts +1 -0
- package/dist/components/input-number/index.js +26 -24
- package/dist/components/input-number/index.js.map +1 -1
- package/dist/components/layout/index.js +8 -8
- package/dist/components/layout/index.js.map +1 -1
- package/dist/components/layout/style.js +1 -1
- package/dist/components/layout/style.js.map +1 -1
- package/dist/components/option/style.js +1 -1
- package/dist/components/option/style.js.map +1 -1
- package/dist/components/popover/index.js +13 -10
- package/dist/components/popover/index.js.map +1 -1
- package/dist/components/popover/style.js +1 -1
- package/dist/components/popover/style.js.map +1 -1
- package/dist/components/radio/index.d.ts +3 -0
- package/dist/components/radio/index.js +22 -18
- package/dist/components/radio/index.js.map +1 -1
- package/dist/components/radio-group/index.js +4 -4
- package/dist/components/segmented/index.d.ts +4 -1
- package/dist/components/segmented/index.js +42 -29
- package/dist/components/segmented/index.js.map +1 -1
- package/dist/components/segmented/style.js +1 -1
- package/dist/components/segmented/style.js.map +1 -1
- package/dist/components/segmented-trigger/style.js +1 -1
- package/dist/components/segmented-trigger/style.js.map +1 -1
- package/dist/components/select/index.js +35 -32
- package/dist/components/select/index.js.map +1 -1
- package/dist/components/select/style.js +1 -1
- package/dist/components/select/style.js.map +1 -1
- package/dist/components/slider/index.js +11 -11
- package/dist/components/switch/index.d.ts +1 -0
- package/dist/components/switch/index.js +34 -32
- package/dist/components/switch/index.js.map +1 -1
- package/dist/components/textarea/index.d.ts +7 -1
- package/dist/components/textarea/index.js +46 -44
- package/dist/components/textarea/index.js.map +1 -1
- package/dist/components/textarea/style.js.map +1 -1
- package/dist/components/theme/index.d.ts +10 -3
- package/dist/components/theme/index.js +133 -93
- package/dist/components/theme/index.js.map +1 -1
- package/dist/components/theme/style.js +1 -1
- package/dist/components/theme/style.js.map +1 -1
- package/dist/components/toast/toast.js +7 -7
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/components/tooltip/index.js +12 -9
- package/dist/components/tooltip/index.js.map +1 -1
- package/dist/components/tooltip/style.js +1 -1
- package/dist/components/tooltip/style.js.map +1 -1
- package/dist/icons/generated/akar-icons-check.d.ts +6 -0
- package/dist/icons/generated/akar-icons-check.js +10 -0
- package/dist/icons/generated/akar-icons-check.js.map +1 -0
- package/dist/icons/generated/bi-check.d.ts +6 -0
- package/dist/icons/generated/bi-check.js +10 -0
- package/dist/icons/generated/bi-check.js.map +1 -0
- package/dist/icons/index.d.ts +2 -0
- package/dist/icons/index.js +3 -1
- package/dist/shared/form-association/field-id.js +9 -0
- package/dist/shared/form-association/field-id.js.map +1 -0
- package/dist/shared/form-association/index.js +9 -1
- package/dist/shared/form-association/index.js.map +1 -1
- package/dist/shared/label-emptiness/index.js +45 -0
- package/dist/shared/label-emptiness/index.js.map +1 -0
- package/dist/shared/option-portal/combobox-shell.js +47 -5
- package/dist/shared/option-portal/combobox-shell.js.map +1 -1
- package/dist/shared/option-portal/index.js +9 -9
- package/dist/shared/overlay/anchored-panel.js +2 -2
- package/dist/shared/overlay/anchored-panel.js.map +1 -1
- package/dist/shared/overlay/open-overlay.js +38 -22
- package/dist/shared/overlay/open-overlay.js.map +1 -1
- package/dist/shared/theme/root-sync.js +48 -0
- package/dist/shared/theme/root-sync.js.map +1 -0
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/switch/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { styleMap } from 'lit/directives/style-map.js'\n\nimport '@/components/icon'\nimport glass from '@/assets/glass.css?inline'\nimport { lucideLoaderCircle } from '@/icons'\nimport { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { attachDragGesture, type DragGestureHandle } from '@/shared/gesture/drag-gesture'\nimport { clamp, normalizeProgress } from '@/shared/gesture/physics'\n\nimport style from './style.css?inline'\n\ninstallPointerFocusSuppression()\n\n@customElement('web-ui-switch')\nexport class WebUiSwitch extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n @state() private _checked = false\n\n get checked(): boolean {\n return this._checked\n }\n\n set checked(v: boolean) {\n const old = this._checked\n this._checked = v\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String, reflect: true }) name = ''\n @property({ type: String }) value = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n @property({ type: Boolean, reflect: true }) loading = false\n @state() private _pressed = false\n @state() private _isDragging = false\n @state() private _dragOffset = 0\n @state() private _dragProgress = 0\n\n private _dragged = false\n private _maxTravel = 20\n private _startOffset = 0\n private _dragGestureHandle: DragGestureHandle | null = null\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._dragGestureHandle?.destroy()\n this._dragGestureHandle = null\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n private readonly _formAssociation = defineFormAssociation<boolean>({\n host: this,\n initialize: () => {\n if (this.hasAttribute('checked')) this._checked = true\n },\n getState: () => this._checked,\n setState: checked => {\n this.checked = checked\n },\n getFormValue: () => (this._checked ? this.value || 'on' : null),\n getFormState: () => String(this._checked),\n restoreState: state => {\n if (typeof state === 'string') this.checked = state === 'true'\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || !this.required || this._checked) internals.setValidity({})\n else internals.setValidity({ valueMissing: true }, '请启用此项')\n }\n\n // 阻止 label 默认行为,避免原生 checkbox 重复触发点击。\n private handleClick(e: Event) {\n e.preventDefault()\n if (this._dragged) {\n this._dragged = false\n return\n }\n if (this._isDisabled || this.loading) return\n const old = this._checked\n this._checked = !old\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private handlePointerDown(e: PointerEvent) {\n if (this._isDisabled || this.loading) return\n this._pressed = true\n\n const track = this.renderRoot.querySelector<HTMLElement>('.wui-switch-track')\n if (track) {\n const trackWidth = track.getBoundingClientRect().width || 40\n // 拖拽时 thumb 的 pressed 布局盒为 20px(scale(1.5) 视觉放大),因此行程按 20px 布局盒钳制;\n // 释放后的 checked 静止位移为 20px(16px thumb),两者由 transition 衔接。\n this._maxTravel = Math.max(1, trackWidth - 4 - 20)\n } else {\n this._maxTravel = 16\n }\n\n this._startOffset = this._checked ? this._maxTravel : 0\n this._dragOffset = this._startOffset\n this._dragProgress = this._checked ? 1 : 0\n\n this._dragGestureHandle?.destroy()\n this._dragGestureHandle = attachDragGesture(e, {\n axis: 'x',\n threshold: 6,\n onMove: info => {\n this._isDragging = true\n const current = clamp(this._startOffset + info.deltaX, 0, this._maxTravel)\n this._dragOffset = current\n this._dragProgress = normalizeProgress(current, 0, this._maxTravel)\n this.requestUpdate()\n },\n onEnd: info => {\n const wasDragging = this._isDragging\n this._isDragging = false\n this._pressed = false\n\n if (wasDragging) {\n this._dragged = true\n let targetChecked = this._checked\n if (info.velocityX > 300) {\n targetChecked = true\n } else if (info.velocityX < -300) {\n targetChecked = false\n } else {\n targetChecked = this._dragProgress >= 0.5\n }\n\n if (targetChecked !== this._checked) {\n const old = this._checked\n this._checked = targetChecked\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n } else {\n this.requestUpdate()\n }\n }\n },\n onCancel: () => {\n this._isDragging = false\n this._pressed = false\n this.requestUpdate()\n }\n })\n }\n\n private handlePointerUp() {\n this._pressed = false\n }\n\n private handlePointerLeave() {\n if (!this._isDragging) {\n this._pressed = false\n }\n }\n\n override render() {\n const isOpen = this._isDragging ? this._dragProgress >= 0.5 : this._checked\n const trackCls = {\n 'wui-switch-track': true,\n 'is-open': isOpen,\n 'is-dragging': this._isDragging,\n 'is-disabled': this._isDisabled || this.loading\n }\n // wui-glass 条件化:静止态实体白 thumb,按压/拖拽时切换为玻璃(backdrop blur +\n // 无填充 + 描边)并放大,回到最初修复不跟手问题时期的视觉结构。\n const thumbCls = {\n 'wui-switch-thumb': true,\n 'wui-glass': this._pressed || this._isDragging,\n 'is-pressed': this._pressed || this._isDragging\n }\n const trackStyle = this._isDragging ? { '--wui-switch-drag-offset': `${this._dragOffset}px` } : {}\n\n return html`\n <label\n class=${classMap(trackCls)}\n style=${styleMap(trackStyle)}\n role=\"switch\"\n aria-checked=${String(this._checked)}\n @click=${this.handleClick}\n @pointerdown=${this.handlePointerDown}\n @pointerup=${this.handlePointerUp}\n @pointercancel=${this.handlePointerUp}\n @pointerleave=${this.handlePointerLeave}\n >\n <input\n type=\"checkbox\"\n .checked=${this._checked}\n ?disabled=${this._isDisabled || this.loading}\n class=\"sr-only\"\n />\n <div class=${classMap(thumbCls)}>\n ${\n this.loading\n ? html`<div class=\"wui-switch-loading\">\n <web-ui-icon .icon=${lucideLoaderCircle} size=\"14\" color=\"#08f\" spin></web-ui-icon>\n </div>`\n : ''\n }\n </div>\n </label>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-switch': WebUiSwitch\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/switch/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { styleMap } from 'lit/directives/style-map.js'\n\nimport '@/components/icon'\nimport glass from '@/assets/glass.css?inline'\nimport { lucideLoaderCircle } from '@/icons'\nimport { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { createFieldId } from '@/shared/form-association/field-id'\nimport { attachDragGesture, type DragGestureHandle } from '@/shared/gesture/drag-gesture'\nimport { clamp, normalizeProgress } from '@/shared/gesture/physics'\n\nimport style from './style.css?inline'\n\ninstallPointerFocusSuppression()\n\n@customElement('web-ui-switch')\nexport class WebUiSwitch extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n @state() private _checked = false\n\n get checked(): boolean {\n return this._checked\n }\n\n set checked(v: boolean) {\n const old = this._checked\n this._checked = v\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String, reflect: true }) name = ''\n @property({ type: String }) value = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n @property({ type: Boolean, reflect: true }) loading = false\n @state() private _pressed = false\n @state() private _isDragging = false\n @state() private _dragOffset = 0\n @state() private _dragProgress = 0\n\n private _dragged = false\n private _maxTravel = 20\n private _startOffset = 0\n private _dragGestureHandle: DragGestureHandle | null = null\n private readonly _fieldId = createFieldId('web-ui-switch')\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._dragGestureHandle?.destroy()\n this._dragGestureHandle = null\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n private readonly _formAssociation = defineFormAssociation<boolean>({\n host: this,\n initialize: () => {\n if (this.hasAttribute('checked')) this._checked = true\n },\n getState: () => this._checked,\n setState: checked => {\n this.checked = checked\n },\n getFormValue: () => (this._checked ? this.value || 'on' : null),\n getFormState: () => String(this._checked),\n restoreState: state => {\n if (typeof state === 'string') this.checked = state === 'true'\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || !this.required || this._checked) internals.setValidity({})\n else internals.setValidity({ valueMissing: true }, '请启用此项')\n }\n\n // 阻止 label 默认行为,避免原生 checkbox 重复触发点击。\n private handleClick(e: Event) {\n e.preventDefault()\n if (this._dragged) {\n this._dragged = false\n return\n }\n if (this._isDisabled || this.loading) return\n const old = this._checked\n this._checked = !old\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private handlePointerDown(e: PointerEvent) {\n if (this._isDisabled || this.loading) return\n this._pressed = true\n\n const track = this.renderRoot.querySelector<HTMLElement>('.wui-switch-track')\n if (track) {\n const trackWidth = track.getBoundingClientRect().width || 40\n // 拖拽时 thumb 的 pressed 布局盒为 20px(scale(1.5) 视觉放大),因此行程按 20px 布局盒钳制;\n // 释放后的 checked 静止位移为 20px(16px thumb),两者由 transition 衔接。\n this._maxTravel = Math.max(1, trackWidth - 4 - 20)\n } else {\n this._maxTravel = 16\n }\n\n this._startOffset = this._checked ? this._maxTravel : 0\n this._dragOffset = this._startOffset\n this._dragProgress = this._checked ? 1 : 0\n\n this._dragGestureHandle?.destroy()\n this._dragGestureHandle = attachDragGesture(e, {\n axis: 'x',\n threshold: 6,\n onMove: info => {\n this._isDragging = true\n const current = clamp(this._startOffset + info.deltaX, 0, this._maxTravel)\n this._dragOffset = current\n this._dragProgress = normalizeProgress(current, 0, this._maxTravel)\n this.requestUpdate()\n },\n onEnd: info => {\n const wasDragging = this._isDragging\n this._isDragging = false\n this._pressed = false\n\n if (wasDragging) {\n this._dragged = true\n let targetChecked = this._checked\n if (info.velocityX > 300) {\n targetChecked = true\n } else if (info.velocityX < -300) {\n targetChecked = false\n } else {\n targetChecked = this._dragProgress >= 0.5\n }\n\n if (targetChecked !== this._checked) {\n const old = this._checked\n this._checked = targetChecked\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n } else {\n this.requestUpdate()\n }\n }\n },\n onCancel: () => {\n this._isDragging = false\n this._pressed = false\n this.requestUpdate()\n }\n })\n }\n\n private handlePointerUp() {\n this._pressed = false\n }\n\n private handlePointerLeave() {\n if (!this._isDragging) {\n this._pressed = false\n }\n }\n\n override render() {\n const isOpen = this._isDragging ? this._dragProgress >= 0.5 : this._checked\n const trackCls = {\n 'wui-switch-track': true,\n 'is-open': isOpen,\n 'is-dragging': this._isDragging,\n 'is-disabled': this._isDisabled || this.loading\n }\n // wui-glass 条件化:静止态实体白 thumb,按压/拖拽时切换为玻璃(backdrop blur +\n // 无填充 + 描边)并放大,回到最初修复不跟手问题时期的视觉结构。\n const thumbCls = {\n 'wui-switch-thumb': true,\n 'wui-glass': this._pressed || this._isDragging,\n 'is-pressed': this._pressed || this._isDragging\n }\n const trackStyle = this._isDragging ? { '--wui-switch-drag-offset': `${this._dragOffset}px` } : {}\n\n return html`\n <label\n class=${classMap(trackCls)}\n style=${styleMap(trackStyle)}\n role=\"switch\"\n aria-checked=${String(this._checked)}\n @click=${this.handleClick}\n @pointerdown=${this.handlePointerDown}\n @pointerup=${this.handlePointerUp}\n @pointercancel=${this.handlePointerUp}\n @pointerleave=${this.handlePointerLeave}\n >\n <input\n id=${this._fieldId}\n type=\"checkbox\"\n .checked=${this._checked}\n ?disabled=${this._isDisabled || this.loading}\n class=\"sr-only\"\n />\n <div class=${classMap(thumbCls)}>\n ${\n this.loading\n ? html`<div class=\"wui-switch-loading\">\n <web-ui-icon .icon=${lucideLoaderCircle} size=\"14\" color=\"#08f\" spin></web-ui-icon>\n </div>`\n : ''\n }\n </div>\n </label>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-switch': WebUiSwitch\n }\n}\n"],"mappings":"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"}
|
|
@@ -386,6 +386,7 @@ export declare class WebUiTextarea extends WebUiTextarea_base {
|
|
|
386
386
|
private _hasSuffix;
|
|
387
387
|
private _textarea;
|
|
388
388
|
private _resizeObserver;
|
|
389
|
+
private readonly _fieldId;
|
|
389
390
|
get value(): string;
|
|
390
391
|
set value(v: string);
|
|
391
392
|
private get _isDisabled();
|
|
@@ -403,8 +404,13 @@ export declare class WebUiTextarea extends WebUiTextarea_base {
|
|
|
403
404
|
private handleFocus;
|
|
404
405
|
private handleBlur;
|
|
405
406
|
private handleNativeChange;
|
|
406
|
-
focus(): void;
|
|
407
|
+
focus(options?: FocusOptions): void;
|
|
407
408
|
blur(): void;
|
|
409
|
+
/**
|
|
410
|
+
* 公共 API:全选当前值。
|
|
411
|
+
*
|
|
412
|
+
* `disabled` 时与 `focus()` 一致不产生效果;原生控件未渲染时安全 no-op。
|
|
413
|
+
*/
|
|
408
414
|
select(): void;
|
|
409
415
|
private focusTextarea;
|
|
410
416
|
private _onSlotChange;
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
|
|
2
2
|
import "../icon/index.js";
|
|
3
|
-
import t from "../../
|
|
4
|
-
import n from "../../
|
|
3
|
+
import t from "../../assets/glass.js";
|
|
4
|
+
import n from "../../icons/generated/jam-close-circle-f.js";
|
|
5
5
|
import { FormAssociated as r, FormAssociationController as i, defineFormAssociation as a, forwardInputValidity as o } from "../../shared/form-association/index.js";
|
|
6
6
|
import "../button/index.js";
|
|
7
|
-
import s from "
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
7
|
+
import { createFieldId as s } from "../../shared/form-association/field-id.js";
|
|
8
|
+
import c from "./style.js";
|
|
9
|
+
import { LitElement as l, html as u, nothing as d, unsafeCSS as f } from "lit";
|
|
10
|
+
import { customElement as p, property as m, state as h } from "lit/decorators.js";
|
|
11
|
+
import { ifDefined as g } from "lit/directives/if-defined.js";
|
|
12
|
+
import { classMap as _ } from "lit/directives/class-map.js";
|
|
13
|
+
import { styleMap as v } from "lit/directives/style-map.js";
|
|
13
14
|
//#region src/components/textarea/index.ts
|
|
14
|
-
var
|
|
15
|
+
var y = class extends r(l) {
|
|
15
16
|
constructor(...e) {
|
|
16
|
-
super(...e), this.placeholder = "", this.name = "", this.disabled = !1, this.readonly = !1, this.required = !1, this.full = !1, this.clearable = !1, this.borderless = !1, this.rows = 3, this.autosize = !1, this.maxHeight = 0, this.ariaLabel = null, this._value = "", this._focused = !1, this._hasPrefix = !1, this._hasSuffix = !1, this._textarea = null, this._resizeObserver = null, this._formAssociation = a({
|
|
17
|
+
super(...e), this.placeholder = "", this.name = "", this.disabled = !1, this.readonly = !1, this.required = !1, this.full = !1, this.clearable = !1, this.borderless = !1, this.rows = 3, this.autosize = !1, this.maxHeight = 0, this.ariaLabel = null, this._value = "", this._focused = !1, this._hasPrefix = !1, this._hasSuffix = !1, this._textarea = null, this._resizeObserver = null, this._fieldId = s("web-ui-textarea"), this._formAssociation = a({
|
|
17
18
|
host: this,
|
|
18
19
|
getState: () => this._value,
|
|
19
20
|
setState: (e) => {
|
|
@@ -28,7 +29,7 @@ var v = class extends r(c) {
|
|
|
28
29
|
}).make(), this._formAssociationController = new i(this, this._formAssociation);
|
|
29
30
|
}
|
|
30
31
|
static {
|
|
31
|
-
this.styles = [
|
|
32
|
+
this.styles = [f(t), f(c)];
|
|
32
33
|
}
|
|
33
34
|
get value() {
|
|
34
35
|
return this._value;
|
|
@@ -80,7 +81,7 @@ var v = class extends r(c) {
|
|
|
80
81
|
this._textarea && this.autosize && (this._textarea.style.height = "auto", this._textarea.style.height = `${this._textarea.scrollHeight}px`);
|
|
81
82
|
}
|
|
82
83
|
handleInput(e) {
|
|
83
|
-
e.target instanceof HTMLTextAreaElement && (this._value = e.target.value, this._formAssociation.sync(), this._syncValidity(), this._autosize());
|
|
84
|
+
this._isDisabled || this.readonly || e.target instanceof HTMLTextAreaElement && (this._value = e.target.value, this._formAssociation.sync(), this._syncValidity(), this._autosize());
|
|
84
85
|
}
|
|
85
86
|
handleFocus() {
|
|
86
87
|
this._isDisabled || (this._focused = !0);
|
|
@@ -89,19 +90,19 @@ var v = class extends r(c) {
|
|
|
89
90
|
this._focused = !1;
|
|
90
91
|
}
|
|
91
92
|
handleNativeChange(e) {
|
|
92
|
-
e.target instanceof HTMLTextAreaElement && (this._value = e.target.value, this._formAssociation.sync(), this._syncValidity(), this.dispatchEvent(new Event("change", {
|
|
93
|
+
this._isDisabled || this.readonly || e.target instanceof HTMLTextAreaElement && (this._value = e.target.value, this._formAssociation.sync(), this._syncValidity(), this.dispatchEvent(new Event("change", {
|
|
93
94
|
bubbles: !0,
|
|
94
95
|
composed: !0
|
|
95
96
|
})));
|
|
96
97
|
}
|
|
97
|
-
focus() {
|
|
98
|
-
this.shadowRoot?.querySelector("textarea")?.focus();
|
|
98
|
+
focus(e) {
|
|
99
|
+
this._isDisabled || this.shadowRoot?.querySelector("textarea")?.focus(e);
|
|
99
100
|
}
|
|
100
101
|
blur() {
|
|
101
102
|
this.shadowRoot?.querySelector("textarea")?.blur();
|
|
102
103
|
}
|
|
103
104
|
select() {
|
|
104
|
-
this.shadowRoot?.querySelector("textarea")?.select();
|
|
105
|
+
this._isDisabled || this.shadowRoot?.querySelector("textarea")?.select();
|
|
105
106
|
}
|
|
106
107
|
focusTextarea() {
|
|
107
108
|
this._isDisabled || this.shadowRoot?.querySelector("textarea")?.focus();
|
|
@@ -122,28 +123,29 @@ var v = class extends r(c) {
|
|
|
122
123
|
}
|
|
123
124
|
render() {
|
|
124
125
|
let e = this.clearable && this._value && !this.readonly;
|
|
125
|
-
return
|
|
126
|
+
return u`
|
|
126
127
|
<div class="wui-glass wui-textarea-inner" @click=${this.focusTextarea}>
|
|
127
|
-
<slot name="prefix" class=${
|
|
128
|
+
<slot name="prefix" class=${_({ empty: !this._hasPrefix })} @slotchange=${this._onSlotChange}></slot>
|
|
128
129
|
<textarea
|
|
130
|
+
id=${this._fieldId}
|
|
129
131
|
placeholder=${this.placeholder}
|
|
130
132
|
name=${this.name}
|
|
131
|
-
aria-label=${
|
|
132
|
-
aria-labelledby=${
|
|
133
|
+
aria-label=${g(this.ariaLabel)}
|
|
134
|
+
aria-labelledby=${g(this.ariaLabelledby)}
|
|
133
135
|
.rows=${this.rows}
|
|
134
|
-
minlength=${
|
|
135
|
-
maxlength=${
|
|
136
|
+
minlength=${g(this.minlength)}
|
|
137
|
+
maxlength=${g(this.maxlength)}
|
|
136
138
|
?disabled=${this._isDisabled}
|
|
137
139
|
?readonly=${this.readonly}
|
|
138
140
|
?required=${this.required}
|
|
139
141
|
.value=${this._value}
|
|
140
|
-
style=${this.maxHeight > 0 ?
|
|
142
|
+
style=${this.maxHeight > 0 ? v({ "max-height": `${this.maxHeight}px` }) : d}
|
|
141
143
|
@input=${this.handleInput}
|
|
142
144
|
@change=${this.handleNativeChange}
|
|
143
145
|
@focus=${this.handleFocus}
|
|
144
146
|
@blur=${this.handleBlur}
|
|
145
147
|
></textarea>
|
|
146
|
-
${e ?
|
|
148
|
+
${e ? u`<web-ui-button
|
|
147
149
|
icon
|
|
148
150
|
variant="ghost"
|
|
149
151
|
size="20"
|
|
@@ -151,64 +153,64 @@ var v = class extends r(c) {
|
|
|
151
153
|
@pointerdown=${this.preventMouseDownBlur}
|
|
152
154
|
@click=${this.handleClear}
|
|
153
155
|
>
|
|
154
|
-
<web-ui-icon .icon=${
|
|
156
|
+
<web-ui-icon .icon=${n} size="14"></web-ui-icon>
|
|
155
157
|
</web-ui-button>` : ""}
|
|
156
|
-
<slot name="suffix" class=${
|
|
158
|
+
<slot name="suffix" class=${_({ empty: !this._hasSuffix })} @slotchange=${this._onSlotChange}></slot>
|
|
157
159
|
</div>
|
|
158
160
|
`;
|
|
159
161
|
}
|
|
160
162
|
};
|
|
161
|
-
e([
|
|
163
|
+
e([m({
|
|
162
164
|
type: String,
|
|
163
165
|
reflect: !0
|
|
164
|
-
})],
|
|
166
|
+
})], y.prototype, "placeholder", void 0), e([m({
|
|
165
167
|
type: String,
|
|
166
168
|
reflect: !0
|
|
167
|
-
})],
|
|
169
|
+
})], y.prototype, "name", void 0), e([m({
|
|
168
170
|
type: Boolean,
|
|
169
171
|
reflect: !0
|
|
170
|
-
})],
|
|
172
|
+
})], y.prototype, "disabled", void 0), e([m({
|
|
171
173
|
type: Boolean,
|
|
172
174
|
reflect: !0
|
|
173
|
-
})],
|
|
175
|
+
})], y.prototype, "readonly", void 0), e([m({
|
|
174
176
|
type: Boolean,
|
|
175
177
|
reflect: !0
|
|
176
|
-
})],
|
|
178
|
+
})], y.prototype, "required", void 0), e([m({
|
|
177
179
|
type: Boolean,
|
|
178
180
|
reflect: !0
|
|
179
|
-
})],
|
|
181
|
+
})], y.prototype, "full", void 0), e([m({
|
|
180
182
|
type: Boolean,
|
|
181
183
|
reflect: !0
|
|
182
|
-
})],
|
|
184
|
+
})], y.prototype, "clearable", void 0), e([m({
|
|
183
185
|
type: Boolean,
|
|
184
186
|
reflect: !0
|
|
185
|
-
})],
|
|
187
|
+
})], y.prototype, "borderless", void 0), e([m({
|
|
186
188
|
type: Number,
|
|
187
189
|
reflect: !0
|
|
188
|
-
})],
|
|
190
|
+
})], y.prototype, "rows", void 0), e([m({
|
|
189
191
|
type: Number,
|
|
190
192
|
reflect: !0
|
|
191
|
-
})],
|
|
193
|
+
})], y.prototype, "minlength", void 0), e([m({
|
|
192
194
|
type: Number,
|
|
193
195
|
reflect: !0
|
|
194
|
-
})],
|
|
196
|
+
})], y.prototype, "maxlength", void 0), e([m({
|
|
195
197
|
type: Boolean,
|
|
196
198
|
reflect: !0
|
|
197
|
-
})],
|
|
199
|
+
})], y.prototype, "autosize", void 0), e([m({
|
|
198
200
|
type: Number,
|
|
199
201
|
reflect: !0,
|
|
200
202
|
attribute: "max-height"
|
|
201
|
-
})],
|
|
203
|
+
})], y.prototype, "maxHeight", void 0), e([m({
|
|
202
204
|
type: String,
|
|
203
205
|
attribute: "aria-label"
|
|
204
|
-
})],
|
|
206
|
+
})], y.prototype, "ariaLabel", void 0), e([m({
|
|
205
207
|
type: String,
|
|
206
208
|
attribute: "aria-labelledby"
|
|
207
|
-
})],
|
|
209
|
+
})], y.prototype, "ariaLabelledby", void 0), e([h()], y.prototype, "_value", void 0), e([h()], y.prototype, "_focused", void 0), e([h()], y.prototype, "_hasPrefix", void 0), e([h()], y.prototype, "_hasSuffix", void 0), e([m({
|
|
208
210
|
type: String,
|
|
209
211
|
reflect: !0
|
|
210
|
-
})],
|
|
212
|
+
})], y.prototype, "value", null), y = e([p("web-ui-textarea")], y);
|
|
211
213
|
//#endregion
|
|
212
|
-
export {
|
|
214
|
+
export { y as WebUiTextarea };
|
|
213
215
|
|
|
214
216
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/textarea/index.ts"],"sourcesContent":["import { html, LitElement, nothing, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { styleMap } from 'lit/directives/style-map.js'\n\nimport '@/components/icon'\nimport '@/components/button'\nimport glass from '@/assets/glass.css?inline'\nimport { jamCloseCircleF } from '@/icons'\nimport {\n FormAssociated,\n defineFormAssociation,\n forwardInputValidity,\n FormAssociationController\n} from '@/shared/form-association'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-textarea')\nexport class WebUiTextarea extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: String, reflect: true }) placeholder = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) readonly = false\n @property({ type: Boolean, reflect: true }) required = false\n @property({ type: Boolean, reflect: true }) full = false\n @property({ type: Boolean, reflect: true }) clearable = false\n @property({ type: Boolean, reflect: true }) borderless = false\n @property({ type: Number, reflect: true }) rows = 3\n @property({ type: Number, reflect: true }) minlength: number | undefined\n @property({ type: Number, reflect: true }) maxlength: number | undefined\n @property({ type: Boolean, reflect: true }) autosize = false\n // 自动高度上限(px);0 表示不限制,随内容无限增高\n @property({ type: Number, reflect: true, attribute: 'max-height' }) maxHeight = 0\n @property({ type: String, attribute: 'aria-label' }) override ariaLabel: string | null = null\n @property({ type: String, attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined\n\n @state() private _value = ''\n @state() private _focused = false\n @state() private _hasPrefix = false\n @state() private _hasSuffix = false\n\n private _textarea: HTMLTextAreaElement | null = null\n private _resizeObserver: ResizeObserver | null = null\n\n @property({ type: String, reflect: true })\n get value(): string {\n return this._value\n }\n\n set value(v: string) {\n const old = this._value\n this._value = v\n this._formAssociation.sync()\n this.requestUpdate('value', old)\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n private readonly _formAssociation = defineFormAssociation<string>({\n host: this,\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n getFormValue: () => this._value,\n getFormState: () => this._value,\n restoreState: state => {\n if (typeof state === 'string') this.value = state\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._teardownAutosize()\n }\n\n override firstUpdated() {\n this._textarea = this.shadowRoot?.querySelector('textarea') ?? null\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('_value')) {\n const textarea = this._getTextarea()\n if (textarea && textarea.value !== this._value) {\n textarea.value = this._value\n }\n }\n if (changed.has('autosize')) {\n if (this.autosize) {\n this._setupAutosize()\n } else {\n this._teardownAutosize(true)\n }\n }\n this._syncValidity()\n this.toggleAttribute('focused', this._focused)\n }\n\n private _getTextarea(): HTMLTextAreaElement | null {\n this._textarea ??= this.shadowRoot?.querySelector('textarea') ?? null\n return this._textarea\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n const textarea = this._getTextarea()\n if (!internals || !textarea || typeof internals.setValidity !== 'function') return\n\n forwardInputValidity(internals, textarea, ['valueMissing', 'tooShort', 'tooLong'], this._isDisabled)\n }\n\n private _setupAutosize() {\n this._teardownAutosize()\n if (typeof ResizeObserver === 'undefined') {\n this._autosize()\n return\n }\n this._resizeObserver = new ResizeObserver(() => {\n this._autosize()\n })\n if (this._textarea) this._resizeObserver.observe(this._textarea)\n this._autosize()\n }\n\n private _teardownAutosize(resetHeight = false) {\n this._resizeObserver?.disconnect()\n this._resizeObserver = null\n if (resetHeight) this._textarea?.style.removeProperty('height')\n }\n\n private _autosize() {\n if (!this._textarea || !this.autosize) return\n this._textarea.style.height = 'auto'\n // height:auto 时 rows 已驱动自然高,scrollHeight 恒 ≥ rows 行高,无需额外 floor;\n // 上限由 CSS max-height(maxHeight 属性)钳制,这里只负责随内容增高,默认无限\n this._textarea.style.height = `${this._textarea.scrollHeight}px`\n }\n\n private handleInput(e: Event) {\n if (!(e.target instanceof HTMLTextAreaElement)) return\n this._value = e.target.value\n this._formAssociation.sync()\n this._syncValidity()\n this._autosize()\n }\n\n private handleFocus() {\n if (!this._isDisabled) this._focused = true\n }\n\n private handleBlur() {\n this._focused = false\n }\n\n // 原生 change 不 composed,被 shadow root 挡住;这里补发 composed 事件,\n // 兑现 $events/README 声明的公共 change 契约。\n private handleNativeChange(e: Event) {\n if (!(e.target instanceof HTMLTextAreaElement)) return\n this._value = e.target.value\n this._formAssociation.sync()\n this._syncValidity()\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n override focus() {\n this.shadowRoot?.querySelector('textarea')?.focus()\n }\n\n override blur() {\n this.shadowRoot?.querySelector('textarea')?.blur()\n }\n\n select() {\n this.shadowRoot?.querySelector('textarea')?.select()\n }\n\n private focusTextarea() {\n if (this._isDisabled) return\n this.shadowRoot?.querySelector('textarea')?.focus()\n }\n\n private _onSlotChange(e: Event) {\n if (!(e.target instanceof HTMLSlotElement)) return\n const slot = e.target\n const hasContent = slot.assignedElements().length > 0\n if (slot.name === 'prefix') this._hasPrefix = hasContent\n if (slot.name === 'suffix') this._hasSuffix = hasContent\n }\n\n private handleClear() {\n if (this._isDisabled || this.readonly) return\n this._value = ''\n this._formAssociation.sync()\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n }\n\n private preventMouseDownBlur(e: Event) {\n e.preventDefault()\n }\n\n override render() {\n // readonly 下不可清除:清空按钮会修改值,与只读语义冲突\n const showClear = this.clearable && this._value && !this.readonly\n\n return html`\n <div class=\"wui-glass wui-textarea-inner\" @click=${this.focusTextarea}>\n <slot name=\"prefix\" class=${classMap({ empty: !this._hasPrefix })} @slotchange=${this._onSlotChange}></slot>\n <textarea\n placeholder=${this.placeholder}\n name=${this.name}\n aria-label=${ifDefined(this.ariaLabel)}\n aria-labelledby=${ifDefined(this.ariaLabelledby)}\n .rows=${this.rows}\n minlength=${ifDefined(this.minlength)}\n maxlength=${ifDefined(this.maxlength)}\n ?disabled=${this._isDisabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n .value=${this._value}\n style=${this.maxHeight > 0 ? styleMap({ 'max-height': `${this.maxHeight}px` }) : nothing}\n @input=${this.handleInput}\n @change=${this.handleNativeChange}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n ></textarea>\n ${\n showClear\n ? html`<web-ui-button\n icon\n variant=\"ghost\"\n size=\"20\"\n aria-label=\"清除\"\n @pointerdown=${this.preventMouseDownBlur}\n @click=${this.handleClear}\n >\n <web-ui-icon .icon=${jamCloseCircleF} size=\"14\"></web-ui-icon>\n </web-ui-button>`\n : ''\n }\n <slot name=\"suffix\" class=${classMap({ empty: !this._hasSuffix })} @slotchange=${this._onSlotChange}></slot>\n </div>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n focus: FocusEvent\n blur: FocusEvent\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-textarea': WebUiTextarea\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/textarea/index.ts"],"sourcesContent":["import { html, LitElement, nothing, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { styleMap } from 'lit/directives/style-map.js'\n\nimport '@/components/icon'\nimport '@/components/button'\nimport glass from '@/assets/glass.css?inline'\nimport { jamCloseCircleF } from '@/icons'\nimport {\n FormAssociated,\n defineFormAssociation,\n forwardInputValidity,\n FormAssociationController\n} from '@/shared/form-association'\nimport { createFieldId } from '@/shared/form-association/field-id'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-textarea')\nexport class WebUiTextarea extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: String, reflect: true }) placeholder = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) readonly = false\n @property({ type: Boolean, reflect: true }) required = false\n @property({ type: Boolean, reflect: true }) full = false\n @property({ type: Boolean, reflect: true }) clearable = false\n @property({ type: Boolean, reflect: true }) borderless = false\n @property({ type: Number, reflect: true }) rows = 3\n @property({ type: Number, reflect: true }) minlength: number | undefined\n @property({ type: Number, reflect: true }) maxlength: number | undefined\n @property({ type: Boolean, reflect: true }) autosize = false\n // 自动高度上限(px);0 表示不限制,随内容无限增高\n @property({ type: Number, reflect: true, attribute: 'max-height' }) maxHeight = 0\n @property({ type: String, attribute: 'aria-label' }) override ariaLabel: string | null = null\n @property({ type: String, attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined\n\n @state() private _value = ''\n @state() private _focused = false\n @state() private _hasPrefix = false\n @state() private _hasSuffix = false\n\n private _textarea: HTMLTextAreaElement | null = null\n private _resizeObserver: ResizeObserver | null = null\n private readonly _fieldId = createFieldId('web-ui-textarea')\n\n @property({ type: String, reflect: true })\n get value(): string {\n return this._value\n }\n\n set value(v: string) {\n const old = this._value\n this._value = v\n this._formAssociation.sync()\n this.requestUpdate('value', old)\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n private readonly _formAssociation = defineFormAssociation<string>({\n host: this,\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n getFormValue: () => this._value,\n getFormState: () => this._value,\n restoreState: state => {\n if (typeof state === 'string') this.value = state\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._teardownAutosize()\n }\n\n override firstUpdated() {\n this._textarea = this.shadowRoot?.querySelector('textarea') ?? null\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('_value')) {\n const textarea = this._getTextarea()\n if (textarea && textarea.value !== this._value) {\n textarea.value = this._value\n }\n }\n if (changed.has('autosize')) {\n if (this.autosize) {\n this._setupAutosize()\n } else {\n this._teardownAutosize(true)\n }\n }\n this._syncValidity()\n this.toggleAttribute('focused', this._focused)\n }\n\n private _getTextarea(): HTMLTextAreaElement | null {\n this._textarea ??= this.shadowRoot?.querySelector('textarea') ?? null\n return this._textarea\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n const textarea = this._getTextarea()\n if (!internals || !textarea || typeof internals.setValidity !== 'function') return\n\n forwardInputValidity(internals, textarea, ['valueMissing', 'tooShort', 'tooLong'], this._isDisabled)\n }\n\n private _setupAutosize() {\n this._teardownAutosize()\n if (typeof ResizeObserver === 'undefined') {\n this._autosize()\n return\n }\n this._resizeObserver = new ResizeObserver(() => {\n this._autosize()\n })\n if (this._textarea) this._resizeObserver.observe(this._textarea)\n this._autosize()\n }\n\n private _teardownAutosize(resetHeight = false) {\n this._resizeObserver?.disconnect()\n this._resizeObserver = null\n if (resetHeight) this._textarea?.style.removeProperty('height')\n }\n\n private _autosize() {\n if (!this._textarea || !this.autosize) return\n this._textarea.style.height = 'auto'\n // height:auto 时 rows 已驱动自然高,scrollHeight 恒 ≥ rows 行高,无需额外 floor;\n // 上限由 CSS max-height(maxHeight 属性)钳制,这里只负责随内容增高,默认无限\n this._textarea.style.height = `${this._textarea.scrollHeight}px`\n }\n\n private handleInput(e: Event) {\n if (this._isDisabled || this.readonly) return\n if (!(e.target instanceof HTMLTextAreaElement)) return\n this._value = e.target.value\n this._formAssociation.sync()\n this._syncValidity()\n this._autosize()\n }\n\n private handleFocus() {\n if (!this._isDisabled) this._focused = true\n }\n\n private handleBlur() {\n this._focused = false\n }\n\n // 原生 change 不 composed,被 shadow root 挡住;这里补发 composed 事件,\n // 兑现 $events/README 声明的公共 change 契约。\n private handleNativeChange(e: Event) {\n if (this._isDisabled || this.readonly) return\n if (!(e.target instanceof HTMLTextAreaElement)) return\n this._value = e.target.value\n this._formAssociation.sync()\n this._syncValidity()\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n override focus(options?: FocusOptions) {\n if (this._isDisabled) return\n this.shadowRoot?.querySelector('textarea')?.focus(options)\n }\n\n override blur() {\n this.shadowRoot?.querySelector('textarea')?.blur()\n }\n\n /**\n * 公共 API:全选当前值。\n *\n * `disabled` 时与 `focus()` 一致不产生效果;原生控件未渲染时安全 no-op。\n */\n select() {\n if (this._isDisabled) return\n this.shadowRoot?.querySelector('textarea')?.select()\n }\n\n private focusTextarea() {\n if (this._isDisabled) return\n this.shadowRoot?.querySelector('textarea')?.focus()\n }\n\n private _onSlotChange(e: Event) {\n if (!(e.target instanceof HTMLSlotElement)) return\n const slot = e.target\n const hasContent = slot.assignedElements().length > 0\n if (slot.name === 'prefix') this._hasPrefix = hasContent\n if (slot.name === 'suffix') this._hasSuffix = hasContent\n }\n\n private handleClear() {\n if (this._isDisabled || this.readonly) return\n this._value = ''\n this._formAssociation.sync()\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n }\n\n private preventMouseDownBlur(e: Event) {\n e.preventDefault()\n }\n\n override render() {\n // readonly 下不可清除:清空按钮会修改值,与只读语义冲突\n const showClear = this.clearable && this._value && !this.readonly\n\n return html`\n <div class=\"wui-glass wui-textarea-inner\" @click=${this.focusTextarea}>\n <slot name=\"prefix\" class=${classMap({ empty: !this._hasPrefix })} @slotchange=${this._onSlotChange}></slot>\n <textarea\n id=${this._fieldId}\n placeholder=${this.placeholder}\n name=${this.name}\n aria-label=${ifDefined(this.ariaLabel)}\n aria-labelledby=${ifDefined(this.ariaLabelledby)}\n .rows=${this.rows}\n minlength=${ifDefined(this.minlength)}\n maxlength=${ifDefined(this.maxlength)}\n ?disabled=${this._isDisabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n .value=${this._value}\n style=${this.maxHeight > 0 ? styleMap({ 'max-height': `${this.maxHeight}px` }) : nothing}\n @input=${this.handleInput}\n @change=${this.handleNativeChange}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n ></textarea>\n ${\n showClear\n ? html`<web-ui-button\n icon\n variant=\"ghost\"\n size=\"20\"\n aria-label=\"清除\"\n @pointerdown=${this.preventMouseDownBlur}\n @click=${this.handleClear}\n >\n <web-ui-icon .icon=${jamCloseCircleF} size=\"14\"></web-ui-icon>\n </web-ui-button>`\n : ''\n }\n <slot name=\"suffix\" class=${classMap({ empty: !this._hasSuffix })} @slotchange=${this._onSlotChange}></slot>\n </div>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n focus: FocusEvent\n blur: FocusEvent\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-textarea': WebUiTextarea\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/textarea/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n --wui-textarea-clear-color: var(\n --wui-color-text-tertiary,\n color-mix(in srgb, var(--wui-color-text) 35%, transparent)\n );\n display: block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.wui-textarea-inner {\n --wui-glass-corner-radius: var(--wui-radius-menu, 18px);\n position: relative;\n\n display: flex;\n gap: 8px;\n align-items: flex-start;\n\n box-sizing: border-box;\n width: var(--wui-textarea-width, 200px);\n min-width: var(--wui-control-size, 36px);\n min-height: var(--wui-control-size, 36px);\n padding: 7.5px 12px;\n border-radius: var(--wui-radius-menu, 18px);\n}\n\n:host([full]) .wui-textarea-inner {\n width: 100%;\n}\n\n:host([borderless]) .wui-textarea-inner {\n border: none;\n background: transparent;\n backdrop-filter: none;\n box-shadow: none;\n}\n\n/* borderless 必须移除 glass 描边环(.wui-glass::before 底环 + 对角光泽),\n 否则无框后仍残留 1px 描边 */\n:host([borderless]) .wui-textarea-inner::before {\n content: none;\n}\n\ntextarea {\n resize: vertical;\n\n display: block;\n flex: 1;\n\n box-sizing: border-box;\n width: 100%;\n margin: 0;\n padding: 0;\n border: none;\n\n /* 表单控件不继承字体;显式继承以对齐宿主排版,避免 UA 默认字体差异 */\n font: inherit;\n font-size: var(--wui-font-size, 14px);\n line-height: 1.5;\n color: var(--wui-color-text, #1b1b1b);\n\n background: transparent;\n outline: none;\n\n &::placeholder {\n color: var(--wui-color-text-secondary, #6a6a6a);\n }\n\n &:disabled {\n cursor: not-allowed;\n }\n\n &:read-only {\n cursor: default;\n }\n}\n\n/* Coarse pointers include iOS Safari, where a sub-16px font triggers focus zoom. */\n@media (pointer: coarse) {\n textarea {\n font-size: max(16px, var(--wui-font-size, 14px));\n }\n}\n\n/* Focus ring 独立成 ::after 层:base/focused 都是显式 box-shadow,保证所有变体都能过渡 */\n.wui-textarea-inner::after {\n pointer-events: none;\n content: '';\n\n position: absolute;\n inset: 0;\n\n border-radius: inherit;\n\n box-shadow:\n inset 0 0 0 1px transparent,\n 0 0 0 var(--wui-focus-ring-width, 3px) transparent;\n\n transition: box-shadow var(--wui-duration-focus, 200ms);\n}\n\n:host([focused]) .wui-textarea-inner::after {\n box-shadow:\n inset 0 0 0 1px var(--wui-color-accent, #08f),\n 0 0 0 var(--wui-focus-ring-width, 3px) var(--wui-color-focus-ring, rgb(0 136 255 / 0.4));\n}\n\
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/textarea/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n --wui-textarea-clear-color: var(\n --wui-color-text-tertiary,\n color-mix(in srgb, var(--wui-color-text) 35%, transparent)\n );\n display: block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.wui-textarea-inner {\n --wui-glass-corner-radius: var(--wui-radius-menu, 18px);\n position: relative;\n\n display: flex;\n gap: 8px;\n align-items: flex-start;\n\n box-sizing: border-box;\n width: var(--wui-textarea-width, 200px);\n min-width: var(--wui-control-size, 36px);\n min-height: var(--wui-control-size, 36px);\n padding: 7.5px 12px;\n border-radius: var(--wui-radius-menu, 18px);\n}\n\n:host([full]) .wui-textarea-inner {\n width: 100%;\n}\n\n:host([borderless]) .wui-textarea-inner {\n border: none;\n background: transparent;\n backdrop-filter: none;\n box-shadow: none;\n}\n\n/* borderless 必须移除 glass 描边环(.wui-glass::before 底环 + 对角光泽),\n 否则无框后仍残留 1px 描边 */\n:host([borderless]) .wui-textarea-inner::before {\n content: none;\n}\n\ntextarea {\n resize: vertical;\n\n display: block;\n flex: 1;\n\n box-sizing: border-box;\n width: 100%;\n margin: 0;\n padding: 0;\n border: none;\n\n /* 表单控件不继承字体;显式继承以对齐宿主排版,避免 UA 默认字体差异 */\n font: inherit;\n font-size: var(--wui-font-size, 14px);\n line-height: 1.5;\n color: var(--wui-color-text, #1b1b1b);\n\n background: transparent;\n outline: none;\n\n &::placeholder {\n color: var(--wui-color-text-secondary, #6a6a6a);\n }\n\n &:disabled {\n cursor: not-allowed;\n }\n\n &:read-only {\n cursor: default;\n }\n}\n\n/* Coarse pointers include iOS Safari, where a sub-16px font triggers focus zoom. */\n@media (pointer: coarse) {\n textarea {\n font-size: max(16px, var(--wui-font-size, 14px));\n }\n}\n\n/* Focus ring 独立成 ::after 层:base/focused 都是显式 box-shadow,保证所有变体都能过渡 */\n.wui-textarea-inner::after {\n pointer-events: none;\n content: '';\n\n position: absolute;\n inset: 0;\n\n border-radius: inherit;\n\n box-shadow:\n inset 0 0 0 1px transparent,\n 0 0 0 var(--wui-focus-ring-width, 3px) transparent;\n\n transition: box-shadow var(--wui-duration-focus, 200ms);\n}\n\n:host([focused]) .wui-textarea-inner::after {\n box-shadow:\n inset 0 0 0 1px var(--wui-color-accent, #08f),\n 0 0 0 var(--wui-focus-ring-width, 3px) var(--wui-color-focus-ring, rgb(0 136 255 / 0.4));\n}\n\nslot {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n\n font-size: var(--wui-font-size, 14px);\n color: var(--wui-color-text-secondary, #6a6a6a);\n}\n\nslot.empty {\n display: none;\n}\n\n/* 复用 web-ui-button icon ghost:仅覆盖颜色为 faint 并对齐首行,保持弱意图清除图标观感;\n 负 margin-left 抵消容器 flex gap,让清除按钮紧贴文本域内容\n 负 margin-right 抵消 button padding,让清除按钮右侧 spacing 视觉上协调 */\n.wui-textarea-inner web-ui-button[variant='ghost'] {\n --wui-button-color: var(--wui-textarea-clear-color);\n\n /* 与首行文字垂直居中对齐:容器 align-items: flex-start 使按钮贴内容区顶部,\n 首行中心 = padding-top + 行高/2;24px 按钮需相对内容区上移 (行高 − 按钮高度) / 2 */\n margin-top: calc((var(--wui-font-size, 14px) * 1.5 - 24px) / 2);\n margin-right: -4px;\n margin-left: -8px;\n}\n"],"mappings":""}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
export type ThemeAppearance = 'light' | 'dark' | 'system';
|
|
3
|
+
export type ResolvedThemeAppearance = 'light' | 'dark';
|
|
3
4
|
export type ThemeMotion = 'full' | 'reduced' | 'system';
|
|
4
5
|
export declare class WebUiTheme extends LitElement {
|
|
5
6
|
static styles: import('lit').CSSResult;
|
|
@@ -7,18 +8,23 @@ export declare class WebUiTheme extends LitElement {
|
|
|
7
8
|
set appearance(v: string | undefined);
|
|
8
9
|
private _appearance?;
|
|
9
10
|
private _appearanceRequest;
|
|
11
|
+
private _resolvedAppearance;
|
|
12
|
+
get resolvedAppearance(): ResolvedThemeAppearance;
|
|
13
|
+
private _setResolvedAppearance;
|
|
14
|
+
private _syncResolvedAppearance;
|
|
15
|
+
private _syncSystemAppearanceSubscription;
|
|
16
|
+
private _unsubscribeSystemAppearance?;
|
|
10
17
|
get motion(): ThemeMotion;
|
|
11
18
|
set motion(v: string);
|
|
12
19
|
private _motion;
|
|
13
|
-
get transition(): boolean;
|
|
14
|
-
set transition(v: boolean);
|
|
15
|
-
private _transition;
|
|
16
20
|
private _transitionOriginListening;
|
|
17
21
|
private _transitionRequested;
|
|
18
22
|
private _warned;
|
|
19
23
|
connectedCallback(): void;
|
|
20
24
|
disconnectedCallback(): void;
|
|
21
25
|
protected updated(): void;
|
|
26
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
27
|
+
private _syncRootPageColorSync;
|
|
22
28
|
getOverlayRoot(): HTMLElement | undefined;
|
|
23
29
|
isReducedMotion(): boolean;
|
|
24
30
|
private _findThemeAncestor;
|
|
@@ -31,6 +37,7 @@ export declare class WebUiTheme extends LitElement {
|
|
|
31
37
|
private _cleanupThemeTransition;
|
|
32
38
|
private _activeTransition?;
|
|
33
39
|
private _transitionCleanup?;
|
|
40
|
+
private _transitionInputSkipCleanup?;
|
|
34
41
|
render(): import('lit').TemplateResult<1>;
|
|
35
42
|
firstUpdated(): void;
|
|
36
43
|
private _hasAppearance;
|