@greypan/web-ui 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.CN.md +59 -20
- package/README.md +55 -15
- package/dist/components/checkbox/index.js +1 -1
- 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/radio/index.js +1 -1
- package/dist/components/radio/index.js.map +1 -1
- package/dist/components/radio/style.js +1 -1
- package/dist/components/radio/style.js.map +1 -1
- package/dist/components/segmented/index.d.ts +2 -0
- package/dist/components/segmented/index.js +18 -11
- 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/index.d.ts +3 -0
- package/dist/components/segmented-trigger/index.js +19 -12
- package/dist/components/segmented-trigger/index.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/types/react.d.ts +5 -4
- package/dist/types/utils.d.ts +4 -11
- package/package.json +3 -3
package/README.CN.md
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
[English](./README.md) | 简体中文
|
|
6
6
|
|
|
7
|
+
## 演示
|
|
8
|
+
|
|
9
|
+
[查看演示](https://pan-z2l0ahvi.github.io/mono/)
|
|
10
|
+
|
|
7
11
|
## 安装
|
|
8
12
|
|
|
9
13
|
```bash
|
|
@@ -56,6 +60,39 @@ function App() {
|
|
|
56
60
|
}
|
|
57
61
|
```
|
|
58
62
|
|
|
63
|
+
#### React 自定义元素事件与布尔属性
|
|
64
|
+
|
|
65
|
+
React 19 按 JSX 键名中的 `on` 后缀原样注册 Custom Element 事件。事件名大小写敏感:`open-change`
|
|
66
|
+
必须绑定为 `onopen-change`,不能写成 `onOpenChange`。标准 `input` 和 `change` 事件仍使用 React
|
|
67
|
+
惯用的 `onInput` 和 `onChange`。默认值为 `true` 的属性应使用驼峰 JavaScript 属性传入,这样 `false`
|
|
68
|
+
才会传递给组件。
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<web-ui-dialog
|
|
72
|
+
open={open}
|
|
73
|
+
lockScroll={false}
|
|
74
|
+
onopen-change={event => setOpen(event.detail.open)}
|
|
75
|
+
/>
|
|
76
|
+
<web-ui-select value={value} onChange={event => setValue(event.currentTarget.value)} />
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
当组件会把子元素移入自身的 Portal Shadow DOM(例如 `web-ui-dropdown` 的菜单项)时,React 根节点的
|
|
80
|
+
合成 `onClick` 无法收到该子元素的事件。需要通过 `ref` 直接绑定原生事件:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
const itemRef = useRef<HTMLElement>(null)
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
const item = itemRef.current
|
|
87
|
+
if (!item) return
|
|
88
|
+
const close = () => setOpen(false)
|
|
89
|
+
item.addEventListener('click', close)
|
|
90
|
+
return () => item.removeEventListener('click', close)
|
|
91
|
+
}, [])
|
|
92
|
+
|
|
93
|
+
<web-ui-dropdown-item ref={itemRef}>粘贴并关闭</web-ui-dropdown-item>
|
|
94
|
+
```
|
|
95
|
+
|
|
59
96
|
### Vue
|
|
60
97
|
|
|
61
98
|
需要 `vue >= 3` 作为可选 peer 依赖。
|
|
@@ -296,12 +333,12 @@ ArrowUp/ArrowDown 键增减数值。
|
|
|
296
333
|
|
|
297
334
|
分段控制——单选按钮组。
|
|
298
335
|
|
|
299
|
-
| 属性 | 类型 | 默认值 | 说明
|
|
300
|
-
| ---------- | --------- | ------- |
|
|
301
|
-
| `value` | `string` | `''` | 当前选中值
|
|
302
|
-
| `name` | `string` | `''` | 表单字段名
|
|
303
|
-
| `disabled` | `boolean` | `false` |
|
|
304
|
-
| `required` | `boolean` | `false` | 必填校验
|
|
336
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
337
|
+
| ---------- | --------- | ------- | ---------------- |
|
|
338
|
+
| `value` | `string` | `''` | 当前选中值 |
|
|
339
|
+
| `name` | `string` | `''` | 表单字段名 |
|
|
340
|
+
| `disabled` | `boolean` | `false` | 禁用全部 trigger |
|
|
341
|
+
| `required` | `boolean` | `false` | 必填校验 |
|
|
305
342
|
|
|
306
343
|
**事件:** `input`, `change`
|
|
307
344
|
|
|
@@ -309,24 +346,24 @@ ArrowUp/ArrowDown 键增减数值。
|
|
|
309
346
|
|
|
310
347
|
与原生 `<form>` 集成(通过 `ElementInternals`)。
|
|
311
348
|
|
|
312
|
-
根据 `value` 同步子 trigger 的 `checked`
|
|
349
|
+
根据 `value` 同步子 trigger 的 `checked` 状态。`disabled` 提供继承的有效禁用状态,不改写 trigger 自身的 `disabled` 属性。直接设 `value` 不派发事件。
|
|
313
350
|
|
|
314
351
|
#### `<web-ui-checkbox-group>`
|
|
315
352
|
|
|
316
353
|
多选复选框组。
|
|
317
354
|
|
|
318
|
-
| 属性 | 类型 | 默认值 | 说明
|
|
319
|
-
| ---------- | ---------- | ------- |
|
|
320
|
-
| `value` | `string[]` | `[]` | 已选项的值数组
|
|
321
|
-
| `name` | `string` | `''` | 表单字段名
|
|
322
|
-
| `disabled` | `boolean` | `false` |
|
|
323
|
-
| `required` | `boolean` | `false` | 必填校验
|
|
355
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
356
|
+
| ---------- | ---------- | ------- | -------------- |
|
|
357
|
+
| `value` | `string[]` | `[]` | 已选项的值数组 |
|
|
358
|
+
| `name` | `string` | `''` | 表单字段名 |
|
|
359
|
+
| `disabled` | `boolean` | `false` | 禁用全部子项 |
|
|
360
|
+
| `required` | `boolean` | `false` | 必填校验 |
|
|
324
361
|
|
|
325
362
|
**事件:** `input`, `change`
|
|
326
363
|
|
|
327
364
|
**插槽:** `default`(投影 `<web-ui-checkbox>` 元素)
|
|
328
365
|
|
|
329
|
-
|
|
366
|
+
同步子 checkbox 的 `checked` 状态。`disabled` 提供继承的有效禁用状态,不改写子项自身的 `disabled` 属性。监听子项 `change` 事件。
|
|
330
367
|
|
|
331
368
|
#### `<web-ui-radio-group>`
|
|
332
369
|
|
|
@@ -336,13 +373,15 @@ ArrowUp/ArrowDown 键增减数值。
|
|
|
336
373
|
| ---------- | --------- | ------- | ------------------------ |
|
|
337
374
|
| `value` | `string` | `''` | 当前选中值 |
|
|
338
375
|
| `name` | `string` | `''` | 表单字段名(传递到子项) |
|
|
339
|
-
| `disabled` | `boolean` | `false` |
|
|
376
|
+
| `disabled` | `boolean` | `false` | 禁用全部子项 |
|
|
340
377
|
| `required` | `boolean` | `false` | 必填校验 |
|
|
341
378
|
|
|
342
379
|
**事件:** `input`, `change`
|
|
343
380
|
|
|
344
381
|
**插槽:** `default`(投影 `<web-ui-radio>` 元素)
|
|
345
382
|
|
|
383
|
+
`disabled` 提供继承的有效禁用状态,不改写子项自身的 `disabled` 属性。
|
|
384
|
+
|
|
346
385
|
---
|
|
347
386
|
|
|
348
387
|
### 按钮
|
|
@@ -760,11 +799,11 @@ toast.updateMessage(id, { message: '上传已完成 60%', heading: '正在上传
|
|
|
760
799
|
|
|
761
800
|
`<web-ui-segmented>` 的分段按钮。
|
|
762
801
|
|
|
763
|
-
| 属性 | 类型 | 默认值 | 说明
|
|
764
|
-
| ---------- | --------- | ------- |
|
|
765
|
-
| `value` | `string` | `''` | 分段值
|
|
766
|
-
| `checked` | `boolean` | `false` | 当前选中
|
|
767
|
-
| `disabled` | `boolean` | `false` |
|
|
802
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
803
|
+
| ---------- | --------- | ------- | ------------------ |
|
|
804
|
+
| `value` | `string` | `''` | 分段值 |
|
|
805
|
+
| `checked` | `boolean` | `false` | 当前选中 |
|
|
806
|
+
| `disabled` | `boolean` | `false` | 单独禁用该 trigger |
|
|
768
807
|
|
|
769
808
|
**事件:** `change`
|
|
770
809
|
|
package/README.md
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
English | [简体中文](./README.CN.md)
|
|
6
6
|
|
|
7
|
+
## Demo
|
|
8
|
+
|
|
9
|
+
[View demo](https://pan-z2l0ahvi.github.io/mono/)
|
|
10
|
+
|
|
7
11
|
## Install
|
|
8
12
|
|
|
9
13
|
```bash
|
|
@@ -56,6 +60,40 @@ function App() {
|
|
|
56
60
|
}
|
|
57
61
|
```
|
|
58
62
|
|
|
63
|
+
#### React custom-element events and boolean properties
|
|
64
|
+
|
|
65
|
+
React 19 registers Custom Element events using the suffix of the JSX `on` key unchanged. Event names are
|
|
66
|
+
case-sensitive: bind `open-change` as `onopen-change`, not `onOpenChange`. Standard `input` and `change`
|
|
67
|
+
events continue to use React's conventional `onInput` and `onChange`. For a default-`true` property, pass the
|
|
68
|
+
camel-cased JavaScript property so `false` reaches the element.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<web-ui-dialog
|
|
72
|
+
open={open}
|
|
73
|
+
lockScroll={false}
|
|
74
|
+
onopen-change={event => setOpen(event.detail.open)}
|
|
75
|
+
/>
|
|
76
|
+
<web-ui-select value={value} onChange={event => setValue(event.currentTarget.value)} />
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
When a component moves a child into its Portal Shadow DOM (such as a `web-ui-dropdown` menu item), React's
|
|
80
|
+
root-delegated synthetic `onClick` cannot receive that child's event. Bind a native listener directly through a
|
|
81
|
+
`ref` instead:
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
const itemRef = useRef<HTMLElement>(null)
|
|
85
|
+
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
const item = itemRef.current
|
|
88
|
+
if (!item) return
|
|
89
|
+
const close = () => setOpen(false)
|
|
90
|
+
item.addEventListener('click', close)
|
|
91
|
+
return () => item.removeEventListener('click', close)
|
|
92
|
+
}, [])
|
|
93
|
+
|
|
94
|
+
<web-ui-dropdown-item ref={itemRef}>Paste and close</web-ui-dropdown-item>
|
|
95
|
+
```
|
|
96
|
+
|
|
59
97
|
### Vue
|
|
60
98
|
|
|
61
99
|
Requires `vue >= 3` as optional peer dependency.
|
|
@@ -304,7 +342,7 @@ Segmented control — single-select button group.
|
|
|
304
342
|
| ---------- | --------- | ------- | ---------------------- |
|
|
305
343
|
| `value` | `string` | `''` | Selected trigger value |
|
|
306
344
|
| `name` | `string` | `''` | Form field name |
|
|
307
|
-
| `disabled` | `boolean` | `false` |
|
|
345
|
+
| `disabled` | `boolean` | `false` | Disables all triggers |
|
|
308
346
|
| `required` | `boolean` | `false` | Required validation |
|
|
309
347
|
|
|
310
348
|
**Events:** `input`, `change`
|
|
@@ -313,24 +351,24 @@ Segmented control — single-select button group.
|
|
|
313
351
|
|
|
314
352
|
Form-associated: integrates with native `<form>` via `ElementInternals`.
|
|
315
353
|
|
|
316
|
-
Manages child trigger `checked` state based on `value`. Setting `value` directly does not dispatch `input`/`change`.
|
|
354
|
+
Manages child trigger `checked` state based on `value`. `disabled` supplies inherited effective disabled state without changing a trigger's own `disabled` property. Setting `value` directly does not dispatch `input`/`change`.
|
|
317
355
|
|
|
318
356
|
#### `<web-ui-checkbox-group>`
|
|
319
357
|
|
|
320
358
|
Checkbox group managing multiple selection.
|
|
321
359
|
|
|
322
|
-
| Attribute | Type | Default | Description
|
|
323
|
-
| ---------- | ---------- | ------- |
|
|
324
|
-
| `value` | `string[]` | `[]` | Selected values
|
|
325
|
-
| `name` | `string` | `''` | Form field name
|
|
326
|
-
| `disabled` | `boolean` | `false` |
|
|
327
|
-
| `required` | `boolean` | `false` | Required validation
|
|
360
|
+
| Attribute | Type | Default | Description |
|
|
361
|
+
| ---------- | ---------- | ------- | --------------------------- |
|
|
362
|
+
| `value` | `string[]` | `[]` | Selected values |
|
|
363
|
+
| `name` | `string` | `''` | Form field name |
|
|
364
|
+
| `disabled` | `boolean` | `false` | Disables all child controls |
|
|
365
|
+
| `required` | `boolean` | `false` | Required validation |
|
|
328
366
|
|
|
329
367
|
**Events:** `input`, `change`
|
|
330
368
|
|
|
331
369
|
**Slots:** `default` (project `<web-ui-checkbox>` elements)
|
|
332
370
|
|
|
333
|
-
Syncs
|
|
371
|
+
Syncs child checkbox `checked` state. `disabled` supplies inherited effective disabled state without changing a child's own `disabled` property. Listens to child `change` events.
|
|
334
372
|
|
|
335
373
|
#### `<web-ui-radio-group>`
|
|
336
374
|
|
|
@@ -340,13 +378,15 @@ Radio group managing single selection.
|
|
|
340
378
|
| ---------- | --------- | ------- | ---------------------------------------- |
|
|
341
379
|
| `value` | `string` | `''` | Selected radio value |
|
|
342
380
|
| `name` | `string` | `''` | Form field name (propagates to children) |
|
|
343
|
-
| `disabled` | `boolean` | `false` |
|
|
381
|
+
| `disabled` | `boolean` | `false` | Disables all child controls |
|
|
344
382
|
| `required` | `boolean` | `false` | Required validation |
|
|
345
383
|
|
|
346
384
|
**Events:** `input`, `change`
|
|
347
385
|
|
|
348
386
|
**Slots:** `default` (project `<web-ui-radio>` elements)
|
|
349
387
|
|
|
388
|
+
`disabled` supplies inherited effective disabled state without changing a child's own `disabled` property.
|
|
389
|
+
|
|
350
390
|
---
|
|
351
391
|
|
|
352
392
|
### Buttons
|
|
@@ -764,11 +804,11 @@ Not form-associated (child of select, not independent submit).
|
|
|
764
804
|
|
|
765
805
|
Segment trigger for `<web-ui-segmented>`.
|
|
766
806
|
|
|
767
|
-
| Attribute | Type | Default | Description
|
|
768
|
-
| ---------- | --------- | ------- |
|
|
769
|
-
| `value` | `string` | `''` | Segment value
|
|
770
|
-
| `checked` | `boolean` | `false` | Currently selected
|
|
771
|
-
| `disabled` | `boolean` | `false` |
|
|
807
|
+
| Attribute | Type | Default | Description |
|
|
808
|
+
| ---------- | --------- | ------- | ---------------------------------- |
|
|
809
|
+
| `value` | `string` | `''` | Segment value |
|
|
810
|
+
| `checked` | `boolean` | `false` | Currently selected |
|
|
811
|
+
| `disabled` | `boolean` | `false` | Individually disables this trigger |
|
|
772
812
|
|
|
773
813
|
**Events:** `change`
|
|
774
814
|
|
|
@@ -78,7 +78,7 @@ var u = class extends r {
|
|
|
78
78
|
"is-checked": this._checked,
|
|
79
79
|
"is-disabled": this._isDisabled
|
|
80
80
|
})}
|
|
81
|
-
tabindex
|
|
81
|
+
tabindex=${this._isDisabled ? "-1" : "0"}
|
|
82
82
|
role="checkbox"
|
|
83
83
|
aria-checked=${String(this._checked)}
|
|
84
84
|
aria-disabled=${String(this._isDisabled)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/checkbox/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'\n\nimport '@/components/icon'\nimport { heroiconsCheck16Solid } from '@/icons'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-checkbox')\nexport class WebUiCheckbox extends LitElement {\n static override styles = unsafeCSS(style)\n static formAssociated = true\n\n /** 内部表单关联实例(connectedCallback 中初始化) */\n private _internals?: ElementInternals\n @state() private _formDisabled = false\n @state() private _groupDisabled = false\n\n /** 内部 checked 状态,通过 getter/setter 暴露为公共 API */\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._syncFormValue()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String }) value = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formDisabled || this._groupDisabled\n }\n\n private get _isManagedByGroup(): boolean {\n return this.closest('web-ui-checkbox-group') !== null\n }\n\n setGroupDisabled(disabled: boolean) {\n this._groupDisabled = disabled\n }\n\n override connectedCallback() {\n super.connectedCallback()\n if (this._internals) return\n this._internals = this.attachInternals()\n if (this.hasAttribute('checked')) {\n this._checked = true\n }\n this._syncFormValue()\n }\n\n formResetCallback() {\n this.checked = this.hasAttribute('checked')\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n override updated() {\n this._syncFormValue()\n this._syncValidity()\n }\n\n private _syncFormValue() {\n this._internals?.setFormValue?.(!this._isManagedByGroup && this._checked ? this.value || 'on' : null)\n }\n\n private _syncValidity() {\n if (!this._internals || typeof this._internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n this._internals.setValidity({})\n return\n }\n this._internals.setValidity({ valueMissing: true }, '请选择此项')\n }\n\n /** 用户点击切换 */\n private handleClick() {\n if (this._isDisabled) return\n const old = this._checked\n this._checked = !old\n this._syncFormValue()\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 handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.handleClick()\n }\n }\n\n override render() {\n const cls = {\n 'wui-checkbox': true,\n 'is-checked': this._checked,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <label\n class=${classMap(cls)}\n tabindex
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/checkbox/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'\n\nimport '@/components/icon'\nimport { heroiconsCheck16Solid } from '@/icons'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-checkbox')\nexport class WebUiCheckbox extends LitElement {\n static override styles = unsafeCSS(style)\n static formAssociated = true\n\n /** 内部表单关联实例(connectedCallback 中初始化) */\n private _internals?: ElementInternals\n @state() private _formDisabled = false\n @state() private _groupDisabled = false\n\n /** 内部 checked 状态,通过 getter/setter 暴露为公共 API */\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._syncFormValue()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String }) value = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formDisabled || this._groupDisabled\n }\n\n private get _isManagedByGroup(): boolean {\n return this.closest('web-ui-checkbox-group') !== null\n }\n\n setGroupDisabled(disabled: boolean) {\n this._groupDisabled = disabled\n }\n\n override connectedCallback() {\n super.connectedCallback()\n if (this._internals) return\n this._internals = this.attachInternals()\n if (this.hasAttribute('checked')) {\n this._checked = true\n }\n this._syncFormValue()\n }\n\n formResetCallback() {\n this.checked = this.hasAttribute('checked')\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n override updated() {\n this._syncFormValue()\n this._syncValidity()\n }\n\n private _syncFormValue() {\n this._internals?.setFormValue?.(!this._isManagedByGroup && this._checked ? this.value || 'on' : null)\n }\n\n private _syncValidity() {\n if (!this._internals || typeof this._internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n this._internals.setValidity({})\n return\n }\n this._internals.setValidity({ valueMissing: true }, '请选择此项')\n }\n\n /** 用户点击切换 */\n private handleClick() {\n if (this._isDisabled) return\n const old = this._checked\n this._checked = !old\n this._syncFormValue()\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 handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.handleClick()\n }\n }\n\n override render() {\n const cls = {\n 'wui-checkbox': true,\n 'is-checked': this._checked,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <label\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"checkbox\"\n aria-checked=${String(this._checked)}\n aria-disabled=${String(this._isDisabled)}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <span class=\"wui-checkbox-box\">\n <span class=\"wui-checkbox-icon\"\n ><web-ui-icon .icon=${heroiconsCheck16Solid} size=\"18\" color=\"#fff\"></web-ui-icon\n ></span>\n </span>\n <span class=\"wui-checkbox-label\"><slot></slot></span>\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-checkbox': WebUiCheckbox\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/components/checkbox/style.css?inline
|
|
2
|
-
var e = "*,:before,:after{box-sizing:border-box}:host{cursor:pointer;display:inline-block}:host([disabled]){cursor:not-allowed
|
|
2
|
+
var e = "*,:before,:after{box-sizing:border-box}:host{cursor:pointer;display:inline-block}:host([disabled]){cursor:not-allowed}.wui-checkbox{cursor:pointer;-webkit-user-select:none;user-select:none;font-size:var(--wui-font-size,14px);color:var(--wui-color-text,#1b1b1b);align-items:center;gap:10px;line-height:1;display:inline-flex}.wui-checkbox:focus-visible{outline:3px solid var(--wui-focus-ring,#08f6);outline-offset:2px;border-radius:2147483647px}.wui-checkbox.is-disabled{cursor:not-allowed;color:var(--wui-color-text-muted,#6a6a6a);opacity:.4}.wui-checkbox-box{background-color:var(--wui-color-surface-raised,#f2f2f7);border-radius:6px;flex-shrink:0;justify-content:center;align-items:center;width:18px;height:18px;transition:background-color .2s,border-color .2s;display:flex}.is-checked .wui-checkbox-box{border-color:var(--wui-color-accent,#08f);background-color:var(--wui-color-accent,#08f)}.wui-checkbox-icon{opacity:0;transition:opacity var(--wui-duration-fast,.16s) ease, transform var(--wui-duration-fast,.16s) var(--wui-ease-out,cubic-bezier(.23, 1, .32, 1));font-size:0;line-height:0;display:block;overflow:hidden;transform:scale(.85)}.is-checked .wui-checkbox-icon{opacity:1;transform:scale(1)}.wui-checkbox-label{pointer-events:none}@media (prefers-reduced-motion:reduce){.wui-checkbox-icon,.is-checked .wui-checkbox-icon{transform:none}}";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { e as default };
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/checkbox/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n cursor: pointer;\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/checkbox/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n cursor: pointer;\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\n.wui-checkbox {\n cursor: pointer;\n user-select: none;\n\n display: inline-flex;\n gap: 10px;\n align-items: center;\n\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-color-text, #1b1b1b);\n\n &:focus-visible {\n border-radius: calc(infinity * 1px);\n outline: 3px solid var(--wui-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n}\n\n.wui-checkbox.is-disabled {\n cursor: not-allowed;\n color: var(--wui-color-text-muted, #6a6a6a);\n opacity: 0.4;\n}\n\n.wui-checkbox-box {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 18px;\n height: 18px;\n border-radius: 6px;\n\n background-color: var(--wui-color-surface-raised, #f2f2f7);\n\n transition:\n background-color 0.2s ease,\n border-color 0.2s ease;\n}\n\n.is-checked .wui-checkbox-box {\n border-color: var(--wui-color-accent, #08f);\n background-color: var(--wui-color-accent, #08f);\n}\n\n.wui-checkbox-icon {\n transform: scale(0.85);\n\n overflow: hidden;\n display: block;\n\n font-size: 0;\n line-height: 0;\n\n opacity: 0;\n\n transition:\n opacity var(--wui-duration-fast, 160ms) ease,\n transform var(--wui-duration-fast, 160ms) var(--wui-ease-out, cubic-bezier(0.23, 1, 0.32, 1));\n}\n\n.is-checked .wui-checkbox-icon {\n transform: scale(1);\n opacity: 1;\n}\n\n.wui-checkbox-label {\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wui-checkbox-icon,\n .is-checked .wui-checkbox-icon {\n transform: none;\n }\n}\n"],"mappings":""}
|
|
@@ -74,7 +74,7 @@ var l = class extends n {
|
|
|
74
74
|
"is-checked": this._checked,
|
|
75
75
|
"is-disabled": this._isDisabled
|
|
76
76
|
})}
|
|
77
|
-
tabindex
|
|
77
|
+
tabindex=${this._isDisabled ? "-1" : "0"}
|
|
78
78
|
role="radio"
|
|
79
79
|
aria-checked=${String(this._checked)}
|
|
80
80
|
aria-disabled=${String(this._isDisabled)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/radio/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'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-radio')\nexport class WebUiRadio extends LitElement {\n static override styles = unsafeCSS(style)\n static formAssociated = true\n\n /** 内部表单关联实例(connectedCallback 中初始化) */\n private _internals?: ElementInternals\n @state() private _formDisabled = false\n @state() private _groupDisabled = false\n\n /** 内部 checked 状态,通过 getter/setter 暴露为公共 API */\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._syncFormValue()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String }) value = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formDisabled || this._groupDisabled\n }\n\n private get _isManagedByGroup(): boolean {\n return this.closest('web-ui-radio-group') !== null\n }\n\n setGroupDisabled(disabled: boolean) {\n this._groupDisabled = disabled\n }\n\n override connectedCallback() {\n super.connectedCallback()\n if (this._internals) return\n this._internals = this.attachInternals()\n if (this.hasAttribute('checked')) {\n this._checked = true\n }\n this._syncFormValue()\n }\n\n formResetCallback() {\n this.checked = this.hasAttribute('checked')\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n override updated() {\n this._syncFormValue()\n this._syncValidity()\n }\n\n private _syncFormValue() {\n this._internals?.setFormValue?.(!this._isManagedByGroup && this._checked ? this.value || 'on' : null)\n }\n\n private _syncValidity() {\n if (!this._internals || typeof this._internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n this._internals.setValidity({})\n return\n }\n this._internals.setValidity({ valueMissing: true }, '请选择一项')\n }\n\n /** 用户点击选中(已选中时不重复触发) */\n private handleClick() {\n if (this._isDisabled || this._checked) return\n this._checked = true\n this._syncFormValue()\n this.requestUpdate('checked', false)\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.handleClick()\n }\n }\n\n override render() {\n const cls = {\n 'wui-radio': true,\n 'is-checked': this._checked,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <label\n class=${classMap(cls)}\n tabindex
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/radio/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'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-radio')\nexport class WebUiRadio extends LitElement {\n static override styles = unsafeCSS(style)\n static formAssociated = true\n\n /** 内部表单关联实例(connectedCallback 中初始化) */\n private _internals?: ElementInternals\n @state() private _formDisabled = false\n @state() private _groupDisabled = false\n\n /** 内部 checked 状态,通过 getter/setter 暴露为公共 API */\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._syncFormValue()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String }) value = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formDisabled || this._groupDisabled\n }\n\n private get _isManagedByGroup(): boolean {\n return this.closest('web-ui-radio-group') !== null\n }\n\n setGroupDisabled(disabled: boolean) {\n this._groupDisabled = disabled\n }\n\n override connectedCallback() {\n super.connectedCallback()\n if (this._internals) return\n this._internals = this.attachInternals()\n if (this.hasAttribute('checked')) {\n this._checked = true\n }\n this._syncFormValue()\n }\n\n formResetCallback() {\n this.checked = this.hasAttribute('checked')\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n override updated() {\n this._syncFormValue()\n this._syncValidity()\n }\n\n private _syncFormValue() {\n this._internals?.setFormValue?.(!this._isManagedByGroup && this._checked ? this.value || 'on' : null)\n }\n\n private _syncValidity() {\n if (!this._internals || typeof this._internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n this._internals.setValidity({})\n return\n }\n this._internals.setValidity({ valueMissing: true }, '请选择一项')\n }\n\n /** 用户点击选中(已选中时不重复触发) */\n private handleClick() {\n if (this._isDisabled || this._checked) return\n this._checked = true\n this._syncFormValue()\n this.requestUpdate('checked', false)\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.handleClick()\n }\n }\n\n override render() {\n const cls = {\n 'wui-radio': true,\n 'is-checked': this._checked,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <label\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"radio\"\n aria-checked=${String(this._checked)}\n aria-disabled=${String(this._isDisabled)}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <span class=\"wui-radio-circle\">\n <span class=\"wui-radio-dot\"></span>\n </span>\n <span class=\"wui-radio-label\"><slot></slot></span>\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-radio': WebUiRadio\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/components/radio/style.css?inline
|
|
2
|
-
var e = "*,:before,:after{box-sizing:border-box}:host{cursor:pointer;display:inline-block}:host([disabled]){cursor:not-allowed
|
|
2
|
+
var e = "*,:before,:after{box-sizing:border-box}:host{cursor:pointer;display:inline-block}:host([disabled]){cursor:not-allowed}.wui-radio{cursor:pointer;-webkit-user-select:none;user-select:none;font-size:var(--wui-font-size,14px);color:var(--wui-color-text,#1b1b1b);align-items:center;gap:10px;line-height:1;display:inline-flex}.wui-radio:focus-visible{outline:3px solid var(--wui-focus-ring,#08f6);outline-offset:2px;border-radius:2147483647px}.wui-radio.is-disabled{cursor:not-allowed;color:var(--wui-color-text-muted,#6a6a6a);opacity:.4}.wui-radio-circle{background-color:var(--wui-color-surface-raised,#f2f2f7);border-radius:2147483647px;flex-shrink:0;justify-content:center;align-items:center;width:18px;height:18px;transition:background-color .2s,border-color .2s;display:flex}.is-checked .wui-radio-circle{background-color:var(--wui-color-accent,#08f)}.wui-radio-dot{opacity:0;background-color:var(--wui-color-surface,#fff);width:8px;height:8px;transition:opacity var(--wui-duration-fast,.16s) ease, transform var(--wui-duration-fast,.16s) var(--wui-ease-out,cubic-bezier(.23, 1, .32, 1));border-radius:2147483647px;transform:scale(.85);box-shadow:inset 0 -1px 2px #0000001f,inset 0 1px 2px #ffffff80,0 0 4px #0088ff4d}.is-checked .wui-radio-dot{opacity:1;transform:scale(1)}.wui-radio-label{pointer-events:none}@media (prefers-reduced-motion:reduce){.wui-radio-dot,.is-checked .wui-radio-dot{transform:none}}";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { e as default };
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/radio/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n cursor: pointer;\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/radio/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n cursor: pointer;\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\n.wui-radio {\n cursor: pointer;\n user-select: none;\n\n display: inline-flex;\n gap: 10px;\n align-items: center;\n\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-color-text, #1b1b1b);\n\n &:focus-visible {\n border-radius: calc(infinity * 1px);\n outline: 3px solid var(--wui-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n}\n\n.wui-radio.is-disabled {\n cursor: not-allowed;\n color: var(--wui-color-text-muted, #6a6a6a);\n opacity: 0.4;\n}\n\n.wui-radio-circle {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 18px;\n height: 18px;\n border-radius: calc(infinity * 1px);\n\n background-color: var(--wui-color-surface-raised, #f2f2f7);\n\n transition:\n background-color 0.2s ease,\n border-color 0.2s ease;\n}\n\n.is-checked .wui-radio-circle {\n background-color: var(--wui-color-accent, #08f);\n}\n\n.wui-radio-dot {\n transform: scale(0.85);\n\n width: 8px;\n height: 8px;\n border-radius: calc(infinity * 1px);\n\n opacity: 0;\n background-color: var(--wui-color-surface, #fff);\n box-shadow:\n inset 0 -1px 2px rgb(0 0 0 / 0.12),\n inset 0 1px 2px rgb(255 255 255 / 0.5),\n 0 0 4px rgb(0 136 255 / 0.3);\n\n transition:\n opacity var(--wui-duration-fast, 160ms) ease,\n transform var(--wui-duration-fast, 160ms) var(--wui-ease-out, cubic-bezier(0.23, 1, 0.32, 1));\n}\n\n.is-checked .wui-radio-dot {\n transform: scale(1);\n opacity: 1;\n}\n\n.wui-radio-label {\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wui-radio-dot,\n .is-checked .wui-radio-dot {\n transform: none;\n }\n}\n"],"mappings":""}
|
|
@@ -7,11 +7,13 @@ export declare class WebUiSegmented extends LitElement {
|
|
|
7
7
|
required: boolean;
|
|
8
8
|
private _internals?;
|
|
9
9
|
private _value;
|
|
10
|
+
private _formDisabled;
|
|
10
11
|
private _initialValue;
|
|
11
12
|
get value(): string;
|
|
12
13
|
set value(v: string);
|
|
13
14
|
private readonly childObserver;
|
|
14
15
|
private _syncPropsToChildren;
|
|
16
|
+
private get _isDisabled();
|
|
15
17
|
private _updateIndicator;
|
|
16
18
|
updated(props: PropertyValues): void;
|
|
17
19
|
connectedCallback(): void;
|
|
@@ -3,10 +3,11 @@ import t from "../../assets/glass.js";
|
|
|
3
3
|
import n from "./style.js";
|
|
4
4
|
import { LitElement as r, html as i, unsafeCSS as a } from "lit";
|
|
5
5
|
import { customElement as o, property as s, state as c } from "lit/decorators.js";
|
|
6
|
+
import { classMap as l } from "lit/directives/class-map.js";
|
|
6
7
|
//#region src/components/segmented/index.ts
|
|
7
|
-
var
|
|
8
|
+
var u = class extends r {
|
|
8
9
|
constructor(...e) {
|
|
9
|
-
super(...e), this.name = "", this.disabled = !1, this.required = !1, this._value = "", this._initialValue = "", this.childObserver = new MutationObserver(() => {
|
|
10
|
+
super(...e), this.name = "", this.disabled = !1, this.required = !1, this._value = "", this._formDisabled = !1, this._initialValue = "", this.childObserver = new MutationObserver(() => {
|
|
10
11
|
this._syncPropsToChildren(), requestAnimationFrame(() => this._updateIndicator());
|
|
11
12
|
});
|
|
12
13
|
}
|
|
@@ -25,9 +26,12 @@ var l = class extends r {
|
|
|
25
26
|
}
|
|
26
27
|
_syncPropsToChildren() {
|
|
27
28
|
this.querySelectorAll("web-ui-segmented-trigger").forEach((e) => {
|
|
28
|
-
e.checked = e.value === this._value, e.
|
|
29
|
+
e.checked = e.value === this._value, e.setGroupDisabled(this._isDisabled);
|
|
29
30
|
});
|
|
30
31
|
}
|
|
32
|
+
get _isDisabled() {
|
|
33
|
+
return this.disabled || this._formDisabled;
|
|
34
|
+
}
|
|
31
35
|
_updateIndicator() {
|
|
32
36
|
let e = this.querySelectorAll("web-ui-segmented-trigger"), t = 0, n = 0;
|
|
33
37
|
e.forEach((e) => {
|
|
@@ -38,7 +42,7 @@ var l = class extends r {
|
|
|
38
42
|
}), this.style.setProperty("--indicator-left", `${t}px`), this.style.setProperty("--indicator-width", `${n}px`);
|
|
39
43
|
}
|
|
40
44
|
updated(e) {
|
|
41
|
-
(e.has("value") || e.has("disabled")) && (this._syncPropsToChildren(), requestAnimationFrame(() => this._updateIndicator()));
|
|
45
|
+
(e.has("value") || e.has("disabled") || e.has("_formDisabled")) && (this._syncPropsToChildren(), requestAnimationFrame(() => this._updateIndicator()));
|
|
42
46
|
}
|
|
43
47
|
connectedCallback() {
|
|
44
48
|
super.connectedCallback(), this._internals = this.attachInternals();
|
|
@@ -52,7 +56,7 @@ var l = class extends r {
|
|
|
52
56
|
super.disconnectedCallback(), this.childObserver.disconnect(), this.removeEventListener("change", this._handleChildChange);
|
|
53
57
|
}
|
|
54
58
|
_handleChildChange(e) {
|
|
55
|
-
if (this.
|
|
59
|
+
if (this._isDisabled) return;
|
|
56
60
|
let t = e.target;
|
|
57
61
|
if (!t.matches?.("web-ui-segmented-trigger")) return;
|
|
58
62
|
let n = t;
|
|
@@ -68,11 +72,14 @@ var l = class extends r {
|
|
|
68
72
|
this.value = this._initialValue;
|
|
69
73
|
}
|
|
70
74
|
formDisabledCallback(e) {
|
|
71
|
-
this.
|
|
75
|
+
this._formDisabled = e;
|
|
72
76
|
}
|
|
73
77
|
render() {
|
|
74
78
|
return i`
|
|
75
|
-
<div class
|
|
79
|
+
<div class=${l({
|
|
80
|
+
"wui-segmented": !0,
|
|
81
|
+
"is-disabled": this._isDisabled
|
|
82
|
+
})}>
|
|
76
83
|
<span class="wui-segmented-indicator wui-glass"></span>
|
|
77
84
|
<slot></slot>
|
|
78
85
|
</div>
|
|
@@ -82,14 +89,14 @@ var l = class extends r {
|
|
|
82
89
|
e([s({
|
|
83
90
|
type: String,
|
|
84
91
|
reflect: !0
|
|
85
|
-
})],
|
|
92
|
+
})], u.prototype, "name", void 0), e([s({
|
|
86
93
|
type: Boolean,
|
|
87
94
|
reflect: !0
|
|
88
|
-
})],
|
|
95
|
+
})], u.prototype, "disabled", void 0), e([s({
|
|
89
96
|
type: Boolean,
|
|
90
97
|
reflect: !0
|
|
91
|
-
})],
|
|
98
|
+
})], u.prototype, "required", void 0), e([c()], u.prototype, "_value", void 0), e([c()], u.prototype, "_formDisabled", void 0), u = e([o("web-ui-segmented")], u);
|
|
92
99
|
//#endregion
|
|
93
|
-
export {
|
|
100
|
+
export { u as WebUiSegmented };
|
|
94
101
|
|
|
95
102
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/segmented/index.ts"],"sourcesContent":["import { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport glass from '@/assets/glass.css?inline'\n\nimport type { WebUiSegmentedTrigger } from '../segmented-trigger'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-segmented')\nexport class WebUiSegmented extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n static formAssociated = true\n\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private _internals?: ElementInternals\n @state() private _value = ''\n private _initialValue = ''\n\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._internals?.setFormValue?.(v)\n this.requestUpdate('value', old)\n }\n\n private readonly childObserver = new MutationObserver(() => {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n })\n\n private _syncPropsToChildren() {\n this.querySelectorAll<WebUiSegmentedTrigger>('web-ui-segmented-trigger').forEach(trigger => {\n trigger.checked = trigger.value === this._value\n trigger.
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/segmented/index.ts"],"sourcesContent":["import { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\n\nimport glass from '@/assets/glass.css?inline'\n\nimport type { WebUiSegmentedTrigger } from '../segmented-trigger'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-segmented')\nexport class WebUiSegmented extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n static formAssociated = true\n\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private _internals?: ElementInternals\n @state() private _value = ''\n @state() private _formDisabled = false\n private _initialValue = ''\n\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._internals?.setFormValue?.(v)\n this.requestUpdate('value', old)\n }\n\n private readonly childObserver = new MutationObserver(() => {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n })\n\n private _syncPropsToChildren() {\n this.querySelectorAll<WebUiSegmentedTrigger>('web-ui-segmented-trigger').forEach(trigger => {\n trigger.checked = trigger.value === this._value\n trigger.setGroupDisabled(this._isDisabled)\n })\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formDisabled\n }\n\n private _updateIndicator() {\n const triggers = this.querySelectorAll<WebUiSegmentedTrigger>('web-ui-segmented-trigger')\n let left = 0\n let width = 0\n\n triggers.forEach(trigger => {\n if (trigger.value === this._value) {\n const triggerRect = trigger.getBoundingClientRect()\n const groupRect = this.getBoundingClientRect()\n left = triggerRect.left - groupRect.left\n width = triggerRect.width\n }\n })\n\n this.style.setProperty('--indicator-left', `${left}px`)\n this.style.setProperty('--indicator-width', `${width}px`)\n }\n\n override updated(props: PropertyValues) {\n if (props.has('value') || props.has('disabled') || props.has('_formDisabled')) {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n }\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._internals = this.attachInternals()\n\n // 仅当属性在连接前未被 property setter 设值时,才从 attribute 读取初始值\n const attrValue = this.getAttribute('value')\n if (attrValue !== null && this._value === '') {\n this._value = attrValue\n }\n this._initialValue = attrValue ?? ''\n this._internals?.setFormValue?.(this._value)\n\n this.childObserver.observe(this, { childList: true })\n this.addEventListener('change', this._handleChildChange)\n }\n\n override firstUpdated() {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.childObserver.disconnect()\n this.removeEventListener('change', this._handleChildChange)\n }\n\n private _handleChildChange(e: Event) {\n if (this._isDisabled) return\n const target = e.target as HTMLElement\n if (!target.matches?.('web-ui-segmented-trigger')) return\n const trigger = target as WebUiSegmentedTrigger\n if (trigger.value === this._value) return\n\n this.value = trigger.value\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n formResetCallback() {\n this.value = this._initialValue\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n override render() {\n return html`\n <div class=${classMap({ 'wui-segmented': true, 'is-disabled': this._isDisabled })}>\n <span class=\"wui-segmented-indicator wui-glass\"></span>\n <slot></slot>\n </div>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-segmented': WebUiSegmented\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/components/segmented/style.css?inline
|
|
2
|
-
var e = "*,:before,:after{box-sizing:border-box}:host{-webkit-user-select:none;user-select:none;display:inline-block}.wui-segmented{background-color:var(--wui-color-surface-raised-mid,#dfdfdf);border-radius:2147483647px;align-items:stretch;padding:4px;display:inline-flex;position:relative}
|
|
2
|
+
var e = "*,:before,:after{box-sizing:border-box}:host{-webkit-user-select:none;user-select:none;display:inline-block}.wui-segmented{background-color:var(--wui-color-surface-raised-mid,#dfdfdf);border-radius:2147483647px;align-items:stretch;padding:4px;display:inline-flex;position:relative}.wui-segmented.is-disabled{cursor:not-allowed;opacity:.4}.wui-segmented.is-disabled .wui-segmented-trigger.is-disabled{opacity:1}.wui-segmented-indicator{z-index:0;top:3px;bottom:3px;left:var(--indicator-left,0);width:var(--indicator-width,0);background-color:var(--wui-color-surface-glass,#fafafa8c);transition:left var(--wui-duration-fast,.16s) var(--wui-ease-standard,cubic-bezier(.77, 0, .175, 1)), width var(--wui-duration-fast,.16s) var(--wui-ease-standard,cubic-bezier(.77, 0, .175, 1));border-radius:2147483647px;position:absolute}";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { e as default };
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/segmented/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n user-select: none;\n display: inline-block;\n}\n\n.wui-segmented {\n position: relative;\n\n display: inline-flex;\n align-items: stretch;\n\n padding: 4px;\n border-radius: calc(infinity * 1px);\n\n background-color: var(--wui-color-surface-raised-mid, #dfdfdf);\n}\n\n
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/segmented/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n user-select: none;\n display: inline-block;\n}\n\n.wui-segmented {\n position: relative;\n\n display: inline-flex;\n align-items: stretch;\n\n padding: 4px;\n border-radius: calc(infinity * 1px);\n\n background-color: var(--wui-color-surface-raised-mid, #dfdfdf);\n}\n\n.wui-segmented.is-disabled {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.wui-segmented.is-disabled .wui-segmented-trigger.is-disabled {\n opacity: 1;\n}\n\n.wui-segmented-indicator {\n position: absolute;\n z-index: 0;\n top: 3px;\n bottom: 3px;\n left: var(--indicator-left, 0);\n\n width: var(--indicator-width, 0);\n border-radius: calc(infinity * 1px);\n\n background-color: var(--wui-color-surface-glass, rgb(250 250 250 / 0.55));\n\n transition:\n left var(--wui-duration-fast, 160ms) var(--wui-ease-standard, cubic-bezier(0.77, 0, 0.175, 1)),\n width var(--wui-duration-fast, 160ms) var(--wui-ease-standard, cubic-bezier(0.77, 0, 0.175, 1));\n}\n"],"mappings":""}
|
|
@@ -4,6 +4,9 @@ export declare class WebUiSegmentedTrigger extends LitElement {
|
|
|
4
4
|
value: string;
|
|
5
5
|
checked: boolean;
|
|
6
6
|
disabled: boolean;
|
|
7
|
+
private _groupDisabled;
|
|
8
|
+
private get _isDisabled();
|
|
9
|
+
setGroupDisabled(disabled: boolean): void;
|
|
7
10
|
private handleClick;
|
|
8
11
|
private handleKeyDown;
|
|
9
12
|
render(): import('lit').TemplateResult<1>;
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import e from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.js";
|
|
2
2
|
import t from "./style.js";
|
|
3
3
|
import { LitElement as n, html as r, unsafeCSS as i } from "lit";
|
|
4
|
-
import { customElement as a, property as o } from "lit/decorators.js";
|
|
5
|
-
import { classMap as
|
|
4
|
+
import { customElement as a, property as o, state as s } from "lit/decorators.js";
|
|
5
|
+
import { classMap as c } from "lit/directives/class-map.js";
|
|
6
6
|
//#region src/components/segmented-trigger/index.ts
|
|
7
|
-
var
|
|
7
|
+
var l = class extends n {
|
|
8
8
|
constructor(...e) {
|
|
9
|
-
super(...e), this.value = "", this.checked = !1, this.disabled = !1;
|
|
9
|
+
super(...e), this.value = "", this.checked = !1, this.disabled = !1, this._groupDisabled = !1;
|
|
10
10
|
}
|
|
11
11
|
static {
|
|
12
12
|
this.styles = i(t);
|
|
13
13
|
}
|
|
14
|
+
get _isDisabled() {
|
|
15
|
+
return this.disabled || this._groupDisabled;
|
|
16
|
+
}
|
|
17
|
+
setGroupDisabled(e) {
|
|
18
|
+
this._groupDisabled = e;
|
|
19
|
+
}
|
|
14
20
|
handleClick() {
|
|
15
|
-
this.
|
|
21
|
+
this._isDisabled || this.checked || (this.checked = !0, this.dispatchEvent(new Event("change", {
|
|
16
22
|
bubbles: !0,
|
|
17
23
|
composed: !0
|
|
18
24
|
})));
|
|
@@ -23,14 +29,15 @@ var c = class extends n {
|
|
|
23
29
|
render() {
|
|
24
30
|
return r`
|
|
25
31
|
<div
|
|
26
|
-
class=${
|
|
32
|
+
class=${c({
|
|
27
33
|
"wui-segmented-trigger": !0,
|
|
28
34
|
"is-checked": this.checked,
|
|
29
|
-
"is-disabled": this.
|
|
35
|
+
"is-disabled": this._isDisabled
|
|
30
36
|
})}
|
|
31
|
-
tabindex
|
|
37
|
+
tabindex=${this._isDisabled ? "-1" : "0"}
|
|
32
38
|
role="option"
|
|
33
39
|
.ariaSelected=${String(this.checked)}
|
|
40
|
+
aria-disabled=${String(this._isDisabled)}
|
|
34
41
|
@click=${this.handleClick}
|
|
35
42
|
@keydown=${this.handleKeyDown}
|
|
36
43
|
>
|
|
@@ -39,14 +46,14 @@ var c = class extends n {
|
|
|
39
46
|
`;
|
|
40
47
|
}
|
|
41
48
|
};
|
|
42
|
-
e([o({ type: String })],
|
|
49
|
+
e([o({ type: String })], l.prototype, "value", void 0), e([o({
|
|
43
50
|
type: Boolean,
|
|
44
51
|
reflect: !0
|
|
45
|
-
})],
|
|
52
|
+
})], l.prototype, "checked", void 0), e([o({
|
|
46
53
|
type: Boolean,
|
|
47
54
|
reflect: !0
|
|
48
|
-
})],
|
|
55
|
+
})], l.prototype, "disabled", void 0), e([s()], l.prototype, "_groupDisabled", void 0), l = e([a("web-ui-segmented-trigger")], l);
|
|
49
56
|
//#endregion
|
|
50
|
-
export {
|
|
57
|
+
export { l as WebUiSegmentedTrigger };
|
|
51
58
|
|
|
52
59
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/segmented-trigger/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-segmented-trigger')\nexport class WebUiSegmentedTrigger extends LitElement {\n static override styles = unsafeCSS(style)\n\n @property({ type: String }) value = ''\n @property({ type: Boolean, reflect: true }) checked = false\n @property({ type: Boolean, reflect: true }) disabled = false\n\n private handleClick() {\n if (this.
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/segmented-trigger/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'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-segmented-trigger')\nexport class WebUiSegmentedTrigger extends LitElement {\n static override styles = unsafeCSS(style)\n\n @property({ type: String }) value = ''\n @property({ type: Boolean, reflect: true }) checked = false\n @property({ type: Boolean, reflect: true }) disabled = false\n @state() private _groupDisabled = false\n\n private get _isDisabled(): boolean {\n return this.disabled || this._groupDisabled\n }\n\n setGroupDisabled(disabled: boolean) {\n this._groupDisabled = disabled\n }\n\n private handleClick() {\n if (this._isDisabled || this.checked) return\n this.checked = true\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.handleClick()\n }\n }\n\n override render() {\n const cls = {\n 'wui-segmented-trigger': true,\n 'is-checked': this.checked,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <div\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"option\"\n .ariaSelected=${String(this.checked)}\n aria-disabled=${String(this._isDisabled)}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <slot></slot>\n </div>\n `\n }\n\n declare readonly $events: {\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-segmented-trigger': WebUiSegmentedTrigger\n }\n}\n"],"mappings":";;;;;;AAOO,IAAM,IAAN,cAAoC,EAAW;;EAMlB,aAHE,KAAA,QAAA,IACkB,KAAA,UAAA,IACC,KAAA,WAAA,IACrB,KAAA,iBAAA;;;EALT,KAAA,SAAA,EAAU,CAAK;;CAOxC,IAAY,cAAuB;EACjC,OAAO,KAAK,YAAY,KAAK;CAC/B;CAEA,iBAAiB,GAAmB;EAClC,KAAK,iBAAiB;CACxB;CAEA,cAAsB;EAChB,KAAK,eAAe,KAAK,YAC7B,KAAK,UAAU,IACf,KAAK,cAAc,IAAI,MAAM,UAAU;GAAE,SAAS;GAAM,UAAU;EAAK,CAAC,CAAC;CAC3E;CAEA,cAAsB,GAAkB;EACtC,CAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,eAAe,GACjB,KAAK,YAAY;CAErB;CAEA,SAAkB;EAOhB,OAAO,CAAI;;gBAEC,EAAS;GAPnB,yBAAyB;GACzB,cAAc,KAAK;GACnB,eAAe,KAAK;EAKD,CAAG,EAAE;mBACX,KAAK,cAAc,OAAO,IAAI;;wBAEzB,OAAO,KAAK,OAAO,EAAE;wBACrB,OAAO,KAAK,WAAW,EAAE;iBAChC,KAAK,YAAY;mBACf,KAAK,cAAc;;;;;CAKpC;AAKF;AAnDG,EAAA,CAAA,EAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,EAAA,WAAA,SAAA,KAAA,CAAA,GACzB,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,WAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,kBAAA,KAAA,CAAA,GAPR,IAAA,EAAA,CAAA,EAAc,0BAA0B,CAAA,GAAA,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/components/segmented-trigger/style.css?inline
|
|
2
|
-
var e = "*,:before,:after{box-sizing:border-box}:host{display:inline-block}:host([disabled]){cursor:not-allowed}.wui-segmented-trigger{cursor:pointer;-webkit-user-select:none;user-select:none;z-index:1;height:34px;font-size:var(--wui-font-size,14px);color:var(--wui-color-text-muted,#6a6a6a);white-space:nowrap;border-radius:2147483647px;justify-content:center;align-items:center;padding:0 16px;line-height:1;transition:color .2s;display:inline-flex;position:relative}.wui-segmented-trigger:focus-visible{outline:3px solid var(--wui-focus-ring,#08f6);outline-offset:2px}.wui-segmented-trigger.is-checked{color:var(--wui-color-text,#1a1a1a)}
|
|
2
|
+
var e = "*,:before,:after{box-sizing:border-box}:host{display:inline-block}:host([disabled]){cursor:not-allowed}.wui-segmented-trigger{cursor:pointer;-webkit-user-select:none;user-select:none;z-index:1;height:34px;font-size:var(--wui-font-size,14px);color:var(--wui-color-text-muted,#6a6a6a);white-space:nowrap;border-radius:2147483647px;justify-content:center;align-items:center;padding:0 16px;line-height:1;transition:color .2s;display:inline-flex;position:relative}.wui-segmented-trigger:focus-visible{outline:3px solid var(--wui-focus-ring,#08f6);outline-offset:2px}.wui-segmented-trigger.is-checked{color:var(--wui-color-text,#1a1a1a)}.wui-segmented-trigger.is-disabled{cursor:not-allowed;opacity:.4}";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { e as default };
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/segmented-trigger/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\n.wui-segmented-trigger {\n cursor: pointer;\n user-select: none;\n\n position: relative;\n z-index: 1;\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n height: 34px;\n padding: 0 16px;\n border-radius: calc(infinity * 1px);\n\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-color-text-muted, #6a6a6a);\n white-space: nowrap;\n\n transition: color 0.2s ease;\n\n &:focus-visible {\n outline: 3px solid var(--wui-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n\n &.is-checked {\n color: var(--wui-color-text, #1a1a1a);\n }\n}\n\n
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/segmented-trigger/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\n.wui-segmented-trigger {\n cursor: pointer;\n user-select: none;\n\n position: relative;\n z-index: 1;\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n height: 34px;\n padding: 0 16px;\n border-radius: calc(infinity * 1px);\n\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-color-text-muted, #6a6a6a);\n white-space: nowrap;\n\n transition: color 0.2s ease;\n\n &:focus-visible {\n outline: 3px solid var(--wui-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n\n &.is-checked {\n color: var(--wui-color-text, #1a1a1a);\n }\n}\n\n.wui-segmented-trigger.is-disabled {\n cursor: not-allowed;\n opacity: 0.4;\n}\n"],"mappings":""}
|
package/dist/types/react.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { DetailedHTMLProps, HTMLAttributes } from 'react';
|
|
2
|
-
import { WebUiAvatar, WebUiBackTop, WebUiBadge, WebUiButton, WebUiButtonGroup, WebUiCheckbox, WebUiCheckboxGroup, WebUiContextMenu, WebUiDialog, WebUiDrawer, WebUiEmpty, WebUiDropdownDivider, WebUiDropdownHeader, WebUiDropdownItem, WebUiDropdown, WebUiIcon, WebUiInput, WebUiInputNumber, WebUiLayout, WebUiOption, WebUiPopover, WebUiRadio, WebUiRadioGroup, WebUiSegmented, WebUiSegmentedTrigger, WebUiSelect, WebUiSlider, WebUiSpinner, WebUiTextarea, WebUiTheme, WebUiToast, WebUiSwitch, WebUiTooltip } from '../components';
|
|
3
|
-
import {
|
|
4
|
-
export type LitReactWrapper<T> = T extends {
|
|
2
|
+
import { WebUiAvatar, WebUiBackTop, WebUiBadge, WebUiButton, WebUiButtonGroup, WebUiCheckbox, WebUiCheckboxGroup, WebUiContextMenu, WebUiDialog, WebUiDrawer, WebUiEmpty, WebUiDropdownDivider, WebUiDropdownHeader, WebUiDropdownItem, WebUiDropdown, WebUiIcon, WebUiInput, WebUiInputNumber, WebUiLayout, WebUiOption, WebUiPopover, WebUiRadio, WebUiRadioGroup, WebUiSegmented, WebUiSegmentedTrigger, WebUiSelect, WebUiSlider, WebUiSpinner, WebUiTextarea, WebUiTheme, WebUiToast, WebUiSwitch, WebUiSvgDrawLines, WebUiTooltip } from '../components';
|
|
3
|
+
import { ExactEventListeners, ExtractProps, OmitLitBase } from './utils';
|
|
4
|
+
export type LitReactWrapper<T extends HTMLElement> = T extends {
|
|
5
5
|
readonly $events: infer E;
|
|
6
|
-
} ? DetailedHTMLProps<ExtractProps<OmitLitBase<T>> &
|
|
6
|
+
} ? DetailedHTMLProps<ExtractProps<OmitLitBase<T>> & ExactEventListeners<E> & HTMLAttributes<T>, T> : DetailedHTMLProps<ExtractProps<OmitLitBase<T>> & HTMLAttributes<T>, T>;
|
|
7
7
|
export interface WebUiComponents {
|
|
8
8
|
'web-ui-avatar': LitReactWrapper<WebUiAvatar>;
|
|
9
9
|
'web-ui-back-top': LitReactWrapper<WebUiBackTop>;
|
|
@@ -26,6 +26,7 @@ export interface WebUiComponents {
|
|
|
26
26
|
'web-ui-select': LitReactWrapper<WebUiSelect>;
|
|
27
27
|
'web-ui-slider': LitReactWrapper<WebUiSlider>;
|
|
28
28
|
'web-ui-spinner': LitReactWrapper<WebUiSpinner>;
|
|
29
|
+
'web-ui-svg-draw-lines': LitReactWrapper<WebUiSvgDrawLines>;
|
|
29
30
|
'web-ui-option': LitReactWrapper<WebUiOption>;
|
|
30
31
|
'web-ui-popover': LitReactWrapper<WebUiPopover>;
|
|
31
32
|
'web-ui-radio': LitReactWrapper<WebUiRadio>;
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -10,17 +10,10 @@ export type ExtractProps<T> = {
|
|
|
10
10
|
};
|
|
11
11
|
export type OmitLitBase<T> = Omit<T, keyof HTMLElement | keyof LitElement>;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
* '
|
|
15
|
-
* 'input' → 'Input'
|
|
13
|
+
* 将 EventMap 转换为 React 19 Custom Element 的精确事件键。
|
|
14
|
+
* 例如 { 'open-change': CustomEvent<...> } → { 'onopen-change'?: (e: CustomEvent<...>) => void }
|
|
16
15
|
*/
|
|
17
|
-
type
|
|
18
|
-
|
|
19
|
-
* 将 EventMap 转换为 on* 事件监听器类型
|
|
20
|
-
* 例如 { input: Event } → { onInput?: (e: Event) => void }
|
|
21
|
-
* { 'visible-change': CustomEvent<...> } → { onVisibleChange?: (e: CustomEvent<...>) => void }
|
|
22
|
-
*/
|
|
23
|
-
export type EventListeners<T> = {
|
|
24
|
-
[K in keyof T & string as `on${KebabToPascal<K>}`]?: (e: T[K]) => void;
|
|
16
|
+
export type ExactEventListeners<T> = {
|
|
17
|
+
[K in keyof T & string as `on${K}`]?: (e: T[K]) => void;
|
|
25
18
|
};
|
|
26
19
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@greypan/web-ui",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Lit-based web components for React, Vue, and vanilla JS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@floating-ui/dom": "^1.8.0",
|
|
44
|
-
"@greypan/
|
|
45
|
-
"@greypan/
|
|
44
|
+
"@greypan/browser-kit": "1.7.4",
|
|
45
|
+
"@greypan/js-kit": "1.6.4"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@iconify-json/jam": "^1.2.3",
|