@greypan/web-ui 10.2.1 → 11.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.
Files changed (210) hide show
  1. package/README.CN.md +132 -68
  2. package/README.md +112 -43
  3. package/dist/assets/menu-portal.js.map +1 -1
  4. package/dist/assets/modal-surface.js.map +1 -1
  5. package/dist/assets/overlay-motion.js +1 -1
  6. package/dist/assets/overlay-motion.js.map +1 -1
  7. package/dist/assets/selection-control.js +1 -1
  8. package/dist/assets/selection-control.js.map +1 -1
  9. package/dist/classes/glass.js +6 -0
  10. package/dist/classes/glass.js.map +1 -0
  11. package/dist/classes/glow.js +6 -0
  12. package/dist/classes/glow.js.map +1 -0
  13. package/dist/classes/style.css +1 -0
  14. package/dist/components/autocomplete/index.d.ts +13 -6
  15. package/dist/components/autocomplete/index.js +34 -14
  16. package/dist/components/autocomplete/index.js.map +1 -1
  17. package/dist/components/autocomplete/style.js +1 -1
  18. package/dist/components/autocomplete/style.js.map +1 -1
  19. package/dist/components/avatar/index.js +2 -2
  20. package/dist/components/avatar/index.js.map +1 -1
  21. package/dist/components/avatar/style.js +1 -1
  22. package/dist/components/avatar/style.js.map +1 -1
  23. package/dist/components/back-top/index.d.ts +4 -0
  24. package/dist/components/back-top/index.js +60 -22
  25. package/dist/components/back-top/index.js.map +1 -1
  26. package/dist/components/back-top/style.js +1 -1
  27. package/dist/components/back-top/style.js.map +1 -1
  28. package/dist/components/badge/index.d.ts +3 -0
  29. package/dist/components/badge/index.js +30 -15
  30. package/dist/components/badge/index.js.map +1 -1
  31. package/dist/components/badge/style.js +1 -1
  32. package/dist/components/badge/style.js.map +1 -1
  33. package/dist/components/button/index.d.ts +4 -0
  34. package/dist/components/button/index.js +32 -19
  35. package/dist/components/button/index.js.map +1 -1
  36. package/dist/components/button/style.js +1 -1
  37. package/dist/components/button/style.js.map +1 -1
  38. package/dist/components/button-group/index.d.ts +3 -0
  39. package/dist/components/button-group/index.js +15 -2
  40. package/dist/components/button-group/index.js.map +1 -1
  41. package/dist/components/button-group/style.js +1 -1
  42. package/dist/components/button-group/style.js.map +1 -1
  43. package/dist/components/checkbox/index.d.ts +1 -1
  44. package/dist/components/checkbox/index.js +7 -7
  45. package/dist/components/checkbox/index.js.map +1 -1
  46. package/dist/components/checkbox/style.js +1 -1
  47. package/dist/components/checkbox/style.js.map +1 -1
  48. package/dist/components/checkbox-group/index.js +1 -1
  49. package/dist/components/checkbox-group/index.js.map +1 -1
  50. package/dist/components/collapse/index.d.ts +8 -6
  51. package/dist/components/collapse/index.js +45 -25
  52. package/dist/components/collapse/index.js.map +1 -1
  53. package/dist/components/collapse/style.js +1 -1
  54. package/dist/components/collapse/style.js.map +1 -1
  55. package/dist/components/context-menu/index.d.ts +60 -60
  56. package/dist/components/context-menu/index.js +2 -2
  57. package/dist/components/context-menu/index.js.map +1 -1
  58. package/dist/components/context-menu/scrim.js.map +1 -1
  59. package/dist/components/context-menu/style.js.map +1 -1
  60. package/dist/components/dialog/index.d.ts +5 -4
  61. package/dist/components/dialog/index.js +6 -3
  62. package/dist/components/dialog/index.js.map +1 -1
  63. package/dist/components/dialog/style.js +1 -1
  64. package/dist/components/dialog/style.js.map +1 -1
  65. package/dist/components/drawer/index.d.ts +8 -8
  66. package/dist/components/drawer/index.js +2 -2
  67. package/dist/components/drawer/index.js.map +1 -1
  68. package/dist/components/drawer/style.js.map +1 -1
  69. package/dist/components/dropdown/index.d.ts +22 -6
  70. package/dist/components/dropdown/index.js +147 -18
  71. package/dist/components/dropdown/index.js.map +1 -1
  72. package/dist/components/dropdown-item/index.js.map +1 -1
  73. package/dist/components/dropdown-item/style.js +1 -1
  74. package/dist/components/dropdown-item/style.js.map +1 -1
  75. package/dist/components/editable-text/index.d.ts +2 -2
  76. package/dist/components/editable-text/index.js +7 -3
  77. package/dist/components/editable-text/index.js.map +1 -1
  78. package/dist/components/editable-text/style.js +1 -1
  79. package/dist/components/editable-text/style.js.map +1 -1
  80. package/dist/components/empty/index.d.ts +3 -3
  81. package/dist/components/empty/index.js.map +1 -1
  82. package/dist/components/image-preview/index.d.ts +5 -5
  83. package/dist/components/image-preview/index.js +9 -9
  84. package/dist/components/image-preview/index.js.map +1 -1
  85. package/dist/components/image-preview/style.js.map +1 -1
  86. package/dist/components/input/index.d.ts +1 -0
  87. package/dist/components/input/index.js +6 -3
  88. package/dist/components/input/index.js.map +1 -1
  89. package/dist/components/input/style.js +1 -1
  90. package/dist/components/input/style.js.map +1 -1
  91. package/dist/components/input-number/index.d.ts +31 -1
  92. package/dist/components/input-number/index.js +281 -22
  93. package/dist/components/input-number/index.js.map +1 -1
  94. package/dist/components/input-number/style.js +1 -1
  95. package/dist/components/input-number/style.js.map +1 -1
  96. package/dist/components/layout/index.d.ts +7 -7
  97. package/dist/components/layout/index.js +47 -42
  98. package/dist/components/layout/index.js.map +1 -1
  99. package/dist/components/layout/style.js +1 -1
  100. package/dist/components/layout/style.js.map +1 -1
  101. package/dist/components/middle-ellipsis/index.d.ts +9 -2
  102. package/dist/components/middle-ellipsis/index.js +68 -10
  103. package/dist/components/middle-ellipsis/index.js.map +1 -1
  104. package/dist/components/middle-ellipsis/truncate.d.ts +1 -1
  105. package/dist/components/middle-ellipsis/truncate.js.map +1 -1
  106. package/dist/components/option/style.js +1 -1
  107. package/dist/components/option/style.js.map +1 -1
  108. package/dist/components/popover/index.d.ts +1 -1
  109. package/dist/components/popover/index.js +1 -1
  110. package/dist/components/popover/index.js.map +1 -1
  111. package/dist/components/popover/style.js +1 -1
  112. package/dist/components/popover/style.js.map +1 -1
  113. package/dist/components/radio/index.d.ts +6 -1
  114. package/dist/components/radio/index.js +34 -24
  115. package/dist/components/radio/index.js.map +1 -1
  116. package/dist/components/radio/interaction.d.ts +4 -0
  117. package/dist/components/radio/interaction.js +17 -0
  118. package/dist/components/radio/interaction.js.map +1 -0
  119. package/dist/components/radio/style.js +1 -1
  120. package/dist/components/radio/style.js.map +1 -1
  121. package/dist/components/radio-group/index.d.ts +23 -1
  122. package/dist/components/radio-group/index.js +220 -29
  123. package/dist/components/radio-group/index.js.map +1 -1
  124. package/dist/components/segmented/index.d.ts +2 -0
  125. package/dist/components/segmented/index.js +74 -18
  126. package/dist/components/segmented/index.js.map +1 -1
  127. package/dist/components/segmented/style.js +1 -1
  128. package/dist/components/segmented/style.js.map +1 -1
  129. package/dist/components/segmented-trigger/index.js +3 -2
  130. package/dist/components/segmented-trigger/index.js.map +1 -1
  131. package/dist/components/segmented-trigger/style.js +1 -1
  132. package/dist/components/segmented-trigger/style.js.map +1 -1
  133. package/dist/components/select/index.d.ts +8 -0
  134. package/dist/components/select/index.js +77 -26
  135. package/dist/components/select/index.js.map +1 -1
  136. package/dist/components/select/style.js +1 -1
  137. package/dist/components/select/style.js.map +1 -1
  138. package/dist/components/slider/index.d.ts +15 -0
  139. package/dist/components/slider/index.js +175 -39
  140. package/dist/components/slider/index.js.map +1 -1
  141. package/dist/components/slider/style.js +1 -1
  142. package/dist/components/slider/style.js.map +1 -1
  143. package/dist/components/spinner/index.d.ts +15 -0
  144. package/dist/components/spinner/index.js +79 -22
  145. package/dist/components/spinner/index.js.map +1 -1
  146. package/dist/components/spinner/style.js +1 -1
  147. package/dist/components/spinner/style.js.map +1 -1
  148. package/dist/components/svg-draw-lines/index.js +48 -12
  149. package/dist/components/svg-draw-lines/index.js.map +1 -1
  150. package/dist/components/switch/index.d.ts +11 -3
  151. package/dist/components/switch/index.js +58 -54
  152. package/dist/components/switch/index.js.map +1 -1
  153. package/dist/components/switch/style.js +1 -1
  154. package/dist/components/switch/style.js.map +1 -1
  155. package/dist/components/textarea/index.js +3 -3
  156. package/dist/components/textarea/index.js.map +1 -1
  157. package/dist/components/textarea/style.js +1 -1
  158. package/dist/components/textarea/style.js.map +1 -1
  159. package/dist/components/theme/index.d.ts +1 -0
  160. package/dist/components/theme/index.js +26 -15
  161. package/dist/components/theme/index.js.map +1 -1
  162. package/dist/components/theme/style.js +1 -1
  163. package/dist/components/theme/style.js.map +1 -1
  164. package/dist/components/toast/style.js +1 -1
  165. package/dist/components/toast/style.js.map +1 -1
  166. package/dist/components/toast/toast.js +2 -2
  167. package/dist/components/toast/toast.js.map +1 -1
  168. package/dist/components/tooltip/index.d.ts +2 -1
  169. package/dist/components/tooltip/index.js +10 -5
  170. package/dist/components/tooltip/index.js.map +1 -1
  171. package/dist/components/tooltip/style.js.map +1 -1
  172. package/dist/scrollbars/index.d.ts +8 -8
  173. package/dist/scrollbars/index.js.map +1 -1
  174. package/dist/scrollbars/internal.js.map +1 -1
  175. package/dist/shared/element-height/index.js.map +1 -1
  176. package/dist/shared/focus/pointer-focus.js +12 -10
  177. package/dist/shared/focus/pointer-focus.js.map +1 -1
  178. package/dist/shared/gesture/drag-gesture.js +4 -4
  179. package/dist/shared/gesture/drag-gesture.js.map +1 -1
  180. package/dist/shared/group-management/index.js +43 -18
  181. package/dist/shared/group-management/index.js.map +1 -1
  182. package/dist/shared/label-emptiness/index.js.map +1 -1
  183. package/dist/shared/menu-behavior/index.js.map +1 -1
  184. package/dist/shared/menu-portal/menu-portal.js +1 -1
  185. package/dist/shared/menu-portal/menu-portal.js.map +1 -1
  186. package/dist/shared/menu-portal/menu-tree.js.map +1 -1
  187. package/dist/shared/option-portal/combobox-shell.js.map +1 -1
  188. package/dist/shared/option-portal/index.js.map +1 -1
  189. package/dist/shared/overlay/anchored-panel.js.map +1 -1
  190. package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
  191. package/dist/shared/overlay/nested-drawer-layers.js.map +1 -1
  192. package/dist/shared/overlay/open-overlay.js.map +1 -1
  193. package/dist/shared/overlay/overlay-root.js +1 -1
  194. package/dist/shared/overlay/overlay-root.js.map +1 -1
  195. package/dist/shared/overlay/overlay.js +7 -1
  196. package/dist/shared/overlay/overlay.js.map +1 -1
  197. package/dist/shared/overlay/portal.js.map +1 -1
  198. package/dist/shared/overlay/presence.js.map +1 -1
  199. package/dist/shared/scroll-lock/scroll-lock.js.map +1 -1
  200. package/dist/shared/theme/root-sync.js.map +1 -1
  201. package/package.json +5 -2
  202. package/dist/assets/glass.js +0 -6
  203. package/dist/assets/glass.js.map +0 -1
  204. package/dist/icons/generated/heroicons-arrow-down-16-solid.d.ts +0 -6
  205. package/dist/icons/generated/heroicons-arrow-up-16-solid.d.ts +0 -6
  206. package/dist/icons/generated/jam-volume.d.ts +0 -8
  207. package/dist/icons/generated/jam-watch-f.d.ts +0 -8
  208. package/dist/icons/generated/ooui-check.d.ts +0 -6
  209. package/dist/icons/generated/radix-icons-check.d.ts +0 -6
  210. package/dist/icons/generated/si-check-alt-fill.d.ts +0 -6
package/README.CN.md CHANGED
@@ -25,17 +25,17 @@ import '@greypan/web-ui'
25
25
  // import '@greypan/web-ui/components/button'
26
26
  ```
27
27
 
28
- subpath 导入只注册它点名的那个组件,页面用到的每个标签都要单独导入。
28
+ subpath 导入只注册它点名的那个组件,页面用到的每个 tag 都要单独导入。
29
29
 
30
30
  ```html
31
31
  <web-ui-button variant="primary">点击我</web-ui-button> <web-ui-icon .icon="${lucidePlus}"></web-ui-icon>
32
32
  ```
33
33
 
34
- ## 滚动条
34
+ ## scrollbar
35
35
 
36
36
  `@greypan/web-ui/scrollbars` 承载全仓统一的 [OverlayScrollbars](https://github.com/KingSora/OverlayScrollbars)
37
- 滚动条行为:对齐 macOS 的主题、滚动时出现并自动隐去、点击轨道滚动到该位置。样式表每份文档导入一次,
38
- 选项传给所用的适配包。
37
+ scrollbar 行为:对齐 macOS 的主题、滚动时出现并自动隐去、点击 track 滚动到该位置。样式表每份文档导入一次,
38
+ option 传给所用的适配包。
39
39
 
40
40
  ```js
41
41
  import '@greypan/web-ui/scrollbars.css'
@@ -51,14 +51,78 @@ import { OverlayScrollbarsComponent } from 'overlayscrollbars-vue' // 或 overla
51
51
  靠它维持可滚动。
52
52
  - 目标必须是「纯粹的滚动容器」。OverlayScrollbars 会把宿主变成 flex 行、把子节点搬进它生成的 viewport,
53
53
  所以宿主自身的布局一旦承重(grid、居中盒子、`ul`/`ol`)就会坏。
54
- - OverlayScrollbars 只改变它被初始化到的那个元素,子元素保持原生滚动条。要覆盖文档滚动条就初始化
54
+ - OverlayScrollbars 只改变它被初始化到的那个元素,子元素保持原生 scrollbar。要覆盖文档 scrollbar 就初始化
55
55
  `document.body`——在那里 `window.scrollY` / `window.scrollTo` 保持原生语义。
56
- - 自带滚动容器的组件(`select`、`autocomplete`、dropdown / context-menu 面板、`dialog`、`drawer`、
57
- `toast`)在各自的 shadow root 内给**组件内部**滚动条上主题。OverlayScrollbars 进不了 shadow
58
- root——它的结构样式与主题类都是文档级选择器——所以组件改为在原生滚动条上读同一组继承的
56
+ - 自带滚动容器的组件(`select`、`autocomplete`、dropdown / context-menu panel、`dialog`、`drawer`、
57
+ `toast`)在各自的 shadow root 内给**组件内部**scrollbar 上主题。OverlayScrollbars 进不了 shadow
58
+ root——它的结构样式与主题类都是文档级选择器——所以组件改为在原生 scrollbar 上读同一组继承的
59
59
  `--wui-scrollbar-*` 颜色(`scrollbar-color` / `scrollbar-width`),并刻意不用 `::-webkit-scrollbar`:
60
- 声明它会让引擎放弃平台的覆盖式滚动条、固定占一条布局宽度,而组件内部滚动条正是不能占宽度。
61
- 导入本样式表,组件内部滚动条才会跟随外观,与整页滚动条同一机制。
60
+ 声明它会让引擎放弃平台的覆盖式 scrollbar、固定占一条布局宽度,而组件内部 scrollbar 正是不能占宽度。
61
+ 导入本样式表,组件内部 scrollbar 才会跟随外观,与整页 scrollbar 同一机制。
62
+
63
+ ## Classes
64
+
65
+ `@greypan/web-ui/classes.css` 汇总可复用的公共 class,组件内部与消费方共用同一份源码:
66
+ `.wui-glass`(毛玻璃表面)与 `.wui-glow`(装饰性背景晕染)。
67
+
68
+ ```js
69
+ import '@greypan/web-ui/classes.css'
70
+ ```
71
+
72
+ ### .wui-glass
73
+
74
+ 给任意容器加 `.wui-glass` 即可获得毛玻璃表面;组件内部(drawer body、dialog / toast、tooltip /
75
+ popover、input 等)用的也是同一份样式。
76
+
77
+ ```html
78
+ <div class="wui-glass">...</div>
79
+ ```
80
+
81
+ - 同时提供半透明底色、`backdrop-filter`(模糊 / 饱和 / 亮度)、元素自身的 inset 高光与投影,
82
+ 以及用 `::before` 挖出的 1px 描边环:环的左上 / 右下受光、右上 / 左下背光,半径由
83
+ `--wui-glass-corner-radius` 控制。
84
+ - 容器需要有确定的盒子尺寸和可被采样的背景。`.wui-glass` 只在宿主没有其他 `position` 时补
85
+ `position: relative`,并移除自身 border(描边由环承担);圆角仍跟随宿主的 `border-radius`。
86
+ - 非 pill 表面应把 `--wui-glass-corner-radius` 覆盖成与自身圆角同源的值,否则角部光影半径与
87
+ 盒形不匹配。颜色 token 由主题给出浅 / 深两套默认值,优先覆盖 token 而不是重写 `backdrop-filter`。
88
+
89
+ | token | 默认值 | 说明 |
90
+ | ------------------------------ | ------------------------- | ---------------------------------------------------- |
91
+ | `--wui-color-surface-glass` | `rgb(250 250 250 / 0.34)` | 半透明底色;深色主题为 `rgb(44 44 46 / 0.42)` |
92
+ | `--wui-glass-blur` | `4px` | `backdrop-filter` 模糊半径;设 `0px` 关闭 |
93
+ | `--wui-glass-saturation` | `160%` | 背景饱和度 |
94
+ | `--wui-glass-brightness` | `1.06` | 背景亮度;深色主题为 `1.02` |
95
+ | `--wui-color-glass-highlight` | `rgb(255 255 255 / 0.9)` | 元素 inset 高光;深色主题为 `rgb(255 255 255 / 0.1)` |
96
+ | `--wui-glass-corner-radius` | `32px` | 描边环径向光影的半径 |
97
+ | `--wui-color-glass-ring` | `rgb(0 0 0 / 0.05)` | 1px 环底色;深色主题为 `rgb(255 255 255 / 0.05)` |
98
+ | `--wui-color-glass-ring-sheen` | `rgb(255 255 255 / 0.5)` | 受光角光泽;深色主题为 `rgb(255 255 255 / 0.2)` |
99
+ | `--wui-color-glass-ring-shade` | `rgb(0 0 0 / 0.03)` | 背光角压暗;深色主题为 `rgb(0 0 0 / 0.5)` |
100
+ | `--wui-shadow-glass` | 四层扩散阴影 | 元素投影;未设置时使用类内默认值 |
101
+
102
+ ### .wui-glow
103
+
104
+ 给任意容器加 `.wui-glow` 即可,不需要额外组件或 DOM;`web-ui-layout` 的 `header-glow` 与
105
+ collapse 的 peek 边缘用的也是同一份样式。
106
+
107
+ ```html
108
+ <div class="wui-glow">...</div>
109
+ ```
110
+
111
+ - 渐变与模糊都是容器的背景层,内容始终位于其上方。容器需要有确定的盒子尺寸;`.wui-glow` 只在
112
+ 宿主没有其他 `position` 时补 `position: relative`,并加 `isolation: isolate`。
113
+ - 默认从容器顶部向下铺 `--wui-color-page` 渐变,再叠 `blur(4px)`;模糊层向下探出 24px 后收尾。
114
+ 容器或祖先的 `overflow: hidden` 会裁掉这段尾巴。
115
+ - 宿主是不透明背景时,渐变会叠在它上方,但模糊采样不到宿主背后的内容——只会模糊自身的纯色背景。
116
+ 想要毛玻璃观感,宿主表面应保持半透明。
117
+
118
+ | token | 默认值 | 说明 |
119
+ | ------------------------------- | -------------------------------------- | ------------------------------------------- |
120
+ | `--wui-glow-color` | `var(--wui-color-page, #fff)` | 渐变起点色 |
121
+ | `--wui-glow-gradient-direction` | `to bottom` | `linear-gradient` 的方向 |
122
+ | `--wui-glow-gradient` | 由起点色与方向生成的 `linear-gradient` | 完整 background-image;设 `none` 关闭渐变 |
123
+ | `--wui-glow-blur` | `4px` | `backdrop-filter` 模糊半径;设 `0px` 关闭 |
124
+ | `--wui-glow-overhang` | `24px` | 模糊层向容器下方探出的高度 |
125
+ | `--wui-glow-fade` | `36px` | 从全强度到透明的衰减总长,应不小于 overhang |
62
126
 
63
127
  ## Vite
64
128
 
@@ -137,7 +201,7 @@ function App() {
137
201
  return (
138
202
  <>
139
203
  <web-ui-button variant="primary" onClick={() => alert('点击')}>
140
- 按钮
204
+ button
141
205
  </web-ui-button>
142
206
  <web-ui-input onInput={e => console.log(e.currentTarget.value)} />
143
207
  </>
@@ -163,7 +227,7 @@ React 19 按 JSX 键名中的 `on` 后缀原样注册 Custom Element 事件。
163
227
  <web-ui-select value={value} onChange={event => setValue(event.currentTarget.value)} />
164
228
  ```
165
229
 
166
- 当组件会把子元素移入自身的 Portal Shadow DOM(例如 `web-ui-dropdown` 的菜单项)时,React 根节点的
230
+ 当组件会把子元素移入自身的 Portal Shadow DOM(例如 `web-ui-dropdown` 的 menu item)时,React 根节点的
167
231
  合成 `onClick` 无法收到该子元素的事件。需要通过 `ref` 直接绑定原生事件:
168
232
 
169
233
  ```tsx
@@ -180,11 +244,11 @@ useEffect(() => {
180
244
  <web-ui-dropdown-item ref={itemRef}>粘贴并关闭</web-ui-dropdown-item>
181
245
  ```
182
246
 
183
- 在 `portal` 模式下,库会把面板内容物理移入浮层 Shadow DOM:
247
+ 在 `portal` 模式下,库会把 panel 内容物理移入 overlay Shadow DOM:
184
248
 
185
- - React 按记录的插入父节点执行删除,因此裸条件子元素(`{condition && <el/>}`)的节点一旦已迁移,在面板打开期间无法删除:commit 失败,且该节点可能在面板关闭时重新出现。
186
- - 请改为在稳定的包装元素内部做条件渲染——React 记录的插入父节点是包装元素,包装元素内部的增删在面板打开期间与开合周期内都保持可用(示例如下)。
187
- - 面板打开期间的裸条件新增(向宿主追加内容)不受影响,会自动迁入面板。
249
+ - React 按记录的插入父节点执行删除,因此裸条件子元素(`{condition && <el/>}`)的节点一旦已迁移,在 panel 打开期间无法删除:commit 失败,且该节点可能在 panel 关闭时重新出现。
250
+ - 请改为在稳定的包装元素内部做条件渲染——React 记录的插入父节点是包装元素,包装元素内部的增删在 panel 打开期间与开合周期内都保持可用(示例如下)。
251
+ - panel 打开期间的裸条件新增(向宿主追加内容)不受影响,会自动迁入 panel。
188
252
  - 保持内容始终挂载、仅切换可见性仍是有效的回退方案。
189
253
 
190
254
  ```tsx
@@ -197,11 +261,11 @@ useEffect(() => {
197
261
 
198
262
  需要 `vue >= 3.5` 作为可选 peer 依赖。
199
263
 
200
- Portal 面板支持实时渲染:浮层打开期间条件新增或删除的内容(`web-ui-select`、`web-ui-autocomplete`、
264
+ Portal panel 支持实时渲染:overlay 打开期间条件新增或删除的内容(`web-ui-select`、`web-ui-autocomplete`、
201
265
  `web-ui-popover`、`web-ui-tooltip`、`web-ui-dropdown`、`web-ui-context-menu` 内的 Vue `v-if`)会按模板序
202
- 自动迁入打开中的面板;关闭时所有内容按原锚点位置恢复,后续 patch 继续正常工作。边界:面板打开期间对
203
- keyed `v-for` 列表做中段 splice 或重排不受支持——Vue 的 keyed children diff 会以已迁入面板的兄弟节点
204
- 计算插入锚点,patch 失败且可能丢项;与编译路径无关(编译模板同样命中)。此类列表更新请在面板关闭后
266
+ 自动迁入打开中的 panel;关闭时所有内容按原锚点位置恢复,后续 patch 继续正常工作。边界:panel 打开期间对
267
+ keyed `v-for` 列表做中段 splice 或重排不受支持——Vue 的 keyed children diff 会以已迁入 panel 的兄弟节点
268
+ 计算插入锚点,patch 失败且可能丢项;与编译路径无关(编译模板同样命中)。此类列表更新请在 panel 关闭后
205
269
  进行,或只做尾部追加/删除。
206
270
 
207
271
  ```ts
@@ -224,7 +288,7 @@ import '@greypan/web-ui/types/vue'
224
288
 
225
289
  ```vue
226
290
  <template>
227
- <web-ui-button variant="primary" @click="handleClick">按钮</web-ui-button>
291
+ <web-ui-button variant="primary" @click="handleClick">button</web-ui-button>
228
292
  <web-ui-input v-model="value" />
229
293
  <web-ui-select :value="framework" @change="framework = $event.target.value" />
230
294
  </template>
@@ -254,7 +318,7 @@ Vue 事件类型零 cast:带值组件上的 `@input`/`@change` 解析到组件
254
318
 
255
319
  `web-ui-*` 元素是公开 DOM 边界。`id`、`class`、`style`、全局 HTML 属性和 `data-*` 保留在 Custom Element 宿主上,
256
320
  不会复制到 Shadow DOM。只有组件文档明确声明语义映射时,原生元素属性才会传递。例如 `web-ui-button` 会把 `type`
257
- 映射到内部按钮,且仅接受 `button`、`submit`、`reset`;非法值会回退为 `button`。
321
+ 映射到内部 button,且仅接受 `button`、`submit`、`reset`;非法值会回退为 `button`。
258
322
 
259
323
  ARIA 属性同样必须显式支持:使用组件文档化的命名属性,而不是通配 `aria-*` 透传。组件拥有自己的 role 和交互状态。
260
324
  `click`、`input`、`change` 等浏览器 composed 原生事件仍是主要交互 API。`open-change` 等 kebab-case 自定义事件
@@ -263,7 +327,7 @@ ARIA 属性同样必须显式支持:使用组件文档化的命名属性,而
263
327
  ### Cursor 行为
264
328
 
265
329
  交互控件使用原生箭头光标,而不是手型光标;disabled 控件使用 `not-allowed`。Slider、Switch 和 Segmented 在
266
- hover 与按压反馈阶段保持箭头光标,仅在真实拖拽进行中切换为 `grabbing`。专用拖拽把手和 resize 控件保留各自
330
+ hover 与按压反馈阶段保持箭头光标,仅在真实拖拽进行中切换为 `grabbing`。专用拖拽 drag bar 和 resize 控件保留各自
267
331
  的专用光标。Cursor 样式位于 Shadow DOM 内,应用层普通选择器无法覆盖。
268
332
 
269
333
  ### 受控状态语义
@@ -278,7 +342,7 @@ hover 与按压反馈阶段保持箭头光标,仅在真实拖拽进行中切
278
342
 
279
343
  **请求-写回模式(仅 dialog 与 drawer 的 `controlled`)。**
280
344
  `controlled=true` 时,用户关闭操作(Escape、backdrop、内置关闭、拖拽释放)只*请求* `open=false`;组件不改自己的
281
- 状态,保持打开,直到Consumer写回 `open=false`。这是模态确认语义——关对话框/抽屉通常是需要Consumer批准的操作(未保存
345
+ 状态,保持打开,直到Consumer写回 `open=false`。这是模态确认语义——关 dialog/drawer 通常是需要Consumer批准的操作(未保存
282
346
  表单、需确认),与即时开合不同,不能由组件自行提交。只有这两个模态组件使用该模式;即时开合家族(collapse、popover、
283
347
  dropdown、tooltip)不需要它。
284
348
 
@@ -287,7 +351,7 @@ dropdown、tooltip)不需要它。
287
351
  (`el.checked = true`)覆盖内部状态。这与原生 `<input type="checkbox">` 一致——**没有 `controlled` prop 是因为
288
352
  值总是可读可写**,React/Vue 层自备受控包装。
289
353
 
290
- 若翻转的持久化需要外部往返(例如开关应只有 API 调用成功后保持开启),使用**乐观更新**路径:
354
+ 若翻转的持久化需要外部往返(例如 switch 应只有 API 调用成功后保持开启),使用**乐观更新**路径:
291
355
 
292
356
  - 立即翻转,然后监听 `change`。
293
357
  - 请求期间设 `loading`,阻断后续交互并显示 spinner。
@@ -303,46 +367,46 @@ dropdown、tooltip)不需要它。
303
367
 
304
368
  ## 所有组件
305
369
 
306
- 每个组件都有自己的文档页,API 参考、行为说明和可交互示例都在 [`docs/`](docs/) 下。下面的表只是索引。
307
-
308
- | 分类 | 组件 |
309
- | --------------------- | --------------------------------------------------------- |
310
- | **表单控件** | [`<web-ui-input>`](docs/input.md) |
311
- | | [`<web-ui-textarea>`](docs/textarea.md) |
312
- | | [`<web-ui-editable-text>`](docs/editable-text.md) |
313
- | | [`<web-ui-input-number>`](docs/input-number.md) |
314
- | | [`<web-ui-select>`](docs/select.md) |
315
- | | [`<web-ui-autocomplete>`](docs/autocomplete.md) |
316
- | | [`<web-ui-slider>`](docs/slider.md) |
317
- | | [`<web-ui-checkbox>`](docs/checkbox.md) |
318
- | | [`<web-ui-radio>`](docs/radio.md) |
319
- | | [`<web-ui-switch>`](docs/switch.md) |
320
- | | [`<web-ui-segmented>`](docs/segmented.md) |
321
- | | [`<web-ui-checkbox-group>`](docs/checkbox-group.md) |
322
- | | [`<web-ui-radio-group>`](docs/radio-group.md) |
323
- | **按钮** | [`<web-ui-button>`](docs/button.md) |
324
- | | [`<web-ui-button-group>`](docs/button-group.md) |
325
- | **浮层 / 模态** | [`<web-ui-dialog>`](docs/dialog.md) |
326
- | | [`<web-ui-drawer>`](docs/drawer.md) |
327
- | | [`imagePreview()`](docs/image-preview.md) |
328
- | **文档流 Disclosure** | [`<web-ui-collapse>`](docs/collapse.md) |
329
- | **浮动** | [`<web-ui-popover>`](docs/popover.md) |
330
- | | [`<web-ui-tooltip>`](docs/tooltip.md) |
331
- | | [`<web-ui-context-menu>`](docs/context-menu.md) |
332
- | **菜单** | [`<web-ui-dropdown>`](docs/dropdown.md) |
333
- | | [`<web-ui-dropdown-item>`](docs/dropdown-item.md) |
334
- | | [`<web-ui-dropdown-divider>`](docs/dropdown-divider.md) |
335
- | | [`<web-ui-dropdown-header>`](docs/dropdown-header.md) |
336
- | **数据展示** | [`<web-ui-avatar>`](docs/avatar.md) |
337
- | | [`<web-ui-badge>`](docs/badge.md) |
338
- | | [`<web-ui-empty>`](docs/empty.md) |
339
- | | [`<web-ui-middle-ellipsis>`](docs/middle-ellipsis.md) |
340
- | | [`<web-ui-icon>`](docs/icon.md) |
341
- | | [`<web-ui-spinner>`](docs/spinner.md) |
342
- | **布局与工具** | [`<web-ui-layout>`](docs/layout.md) |
343
- | | [`<web-ui-back-top>`](docs/back-top.md) |
344
- | | [`<web-ui-svg-draw-lines>`](docs/svg-draw-lines.md) |
345
- | | [`<web-ui-theme>`](docs/theme.md) |
346
- | **通知** | [`<web-ui-toast>`](docs/toast.md) |
347
- | **子项** | [`<web-ui-option>`](docs/option.md) |
348
- | | [`<web-ui-segmented-trigger>`](docs/segmented-trigger.md) |
370
+ 每个组件都有自己的文档页,API 参考、行为说明和可交互示例都在 [`docs/`](./docs/) 下。下面的表只是索引。
371
+
372
+ | 分类 | 组件 |
373
+ | --------------------- | ----------------------------------------------------------- |
374
+ | **表单控件** | [`<web-ui-input>`](./docs/input.md) |
375
+ | | [`<web-ui-textarea>`](./docs/textarea.md) |
376
+ | | [`<web-ui-editable-text>`](./docs/editable-text.md) |
377
+ | | [`<web-ui-input-number>`](./docs/input-number.md) |
378
+ | | [`<web-ui-select>`](./docs/select.md) |
379
+ | | [`<web-ui-autocomplete>`](./docs/autocomplete.md) |
380
+ | | [`<web-ui-slider>`](./docs/slider.md) |
381
+ | | [`<web-ui-checkbox>`](./docs/checkbox.md) |
382
+ | | [`<web-ui-radio>`](./docs/radio.md) |
383
+ | | [`<web-ui-switch>`](./docs/switch.md) |
384
+ | | [`<web-ui-segmented>`](./docs/segmented.md) |
385
+ | | [`<web-ui-checkbox-group>`](./docs/checkbox-group.md) |
386
+ | | [`<web-ui-radio-group>`](./docs/radio-group.md) |
387
+ | **button** | [`<web-ui-button>`](./docs/button.md) |
388
+ | | [`<web-ui-button-group>`](./docs/button-group.md) |
389
+ | **overlay / 模态** | [`<web-ui-dialog>`](./docs/dialog.md) |
390
+ | | [`<web-ui-drawer>`](./docs/drawer.md) |
391
+ | | [`imagePreview()`](./docs/image-preview.md) |
392
+ | **文档流 Disclosure** | [`<web-ui-collapse>`](./docs/collapse.md) |
393
+ | **浮动** | [`<web-ui-popover>`](./docs/popover.md) |
394
+ | | [`<web-ui-tooltip>`](./docs/tooltip.md) |
395
+ | | [`<web-ui-context-menu>`](./docs/context-menu.md) |
396
+ | **menu** | [`<web-ui-dropdown>`](./docs/dropdown.md) |
397
+ | | [`<web-ui-dropdown-item>`](./docs/dropdown-item.md) |
398
+ | | [`<web-ui-dropdown-divider>`](./docs/dropdown-divider.md) |
399
+ | | [`<web-ui-dropdown-header>`](./docs/dropdown-header.md) |
400
+ | **数据展示** | [`<web-ui-avatar>`](./docs/avatar.md) |
401
+ | | [`<web-ui-badge>`](./docs/badge.md) |
402
+ | | [`<web-ui-empty>`](./docs/empty.md) |
403
+ | | [`<web-ui-middle-ellipsis>`](./docs/middle-ellipsis.md) |
404
+ | | [`<web-ui-icon>`](./docs/icon.md) |
405
+ | | [`<web-ui-spinner>`](./docs/spinner.md) |
406
+ | **布局与工具** | [`<web-ui-layout>`](./docs/layout.md) |
407
+ | | [`<web-ui-back-top>`](./docs/back-top.md) |
408
+ | | [`<web-ui-svg-draw-lines>`](./docs/svg-draw-lines.md) |
409
+ | | [`<web-ui-theme>`](./docs/theme.md) |
410
+ | **通知** | [`<web-ui-toast>`](./docs/toast.md) |
411
+ | **子项** | [`<web-ui-option>`](./docs/option.md) |
412
+ | | [`<web-ui-segmented-trigger>`](./docs/segmented-trigger.md) |
package/README.md CHANGED
@@ -64,6 +64,75 @@ import { OverlayScrollbarsComponent } from 'overlayscrollbars-react' // or overl
64
64
  not do. Import this stylesheet for the internal scrollbars to follow the appearance, just like the
65
65
  page-level ones.
66
66
 
67
+ ## Classes
68
+
69
+ `@greypan/web-ui/classes.css` bundles the reusable public classes shared by components and consumers:
70
+ `.wui-glass` (frosted surface) and `.wui-glow` (decorative backdrop).
71
+
72
+ ```js
73
+ import '@greypan/web-ui/classes.css'
74
+ ```
75
+
76
+ ### .wui-glass
77
+
78
+ Add `.wui-glass` to any container for a frosted surface. Components use the same stylesheet internally
79
+ (drawer body, dialog / toast, tooltip / popover, input, and so on).
80
+
81
+ ```html
82
+ <div class="wui-glass">...</div>
83
+ ```
84
+
85
+ - It provides the translucent background, the `backdrop-filter` (blur / saturation / brightness), the
86
+ element's own inset highlight and shadow, and a 1px ring cut out with `::before`: the ring lights the
87
+ top-left / bottom-right corners and shades the top-right / bottom-left ones, with the radius controlled
88
+ by `--wui-glass-corner-radius`.
89
+ - The container needs a box size and a background that can be sampled. `.wui-glass` only adds
90
+ `position: relative` when the host has no other `position`, and removes the host's own border (the ring
91
+ replaces it); the corner radius still follows the host's `border-radius`.
92
+ - For non-pill surfaces, override `--wui-glass-corner-radius` with a value derived from the element's own
93
+ radius, otherwise the corner lighting will not match the box shape. Colours come from the theme with
94
+ separate light / dark defaults; prefer overriding tokens over rewriting `backdrop-filter`.
95
+
96
+ | token | default | description |
97
+ | ------------------------------ | ------------------------- | ---------------------------------------------------- |
98
+ | `--wui-color-surface-glass` | `rgb(250 250 250 / 0.34)` | Translucent surface; `rgb(44 44 46 / 0.42)` in dark |
99
+ | `--wui-glass-blur` | `4px` | `backdrop-filter` radius; set `0px` to disable |
100
+ | `--wui-glass-saturation` | `160%` | Backdrop saturation |
101
+ | `--wui-glass-brightness` | `1.06` | Backdrop brightness; `1.02` in dark |
102
+ | `--wui-color-glass-highlight` | `rgb(255 255 255 / 0.9)` | Inset highlight; `rgb(255 255 255 / 0.1)` in dark |
103
+ | `--wui-glass-corner-radius` | `32px` | Radius of the ring's corner lighting |
104
+ | `--wui-color-glass-ring` | `rgb(0 0 0 / 0.05)` | 1px ring base; `rgb(255 255 255 / 0.05)` in dark |
105
+ | `--wui-color-glass-ring-sheen` | `rgb(255 255 255 / 0.5)` | Lit-corner sheen; `rgb(255 255 255 / 0.2)` in dark |
106
+ | `--wui-color-glass-ring-shade` | `rgb(0 0 0 / 0.03)` | Unlit-corner shade; `rgb(0 0 0 / 0.5)` in dark |
107
+ | `--wui-shadow-glass` | four-layer diffuse shadow | Element shadow; the class default applies when unset |
108
+
109
+ ### .wui-glow
110
+
111
+ Add `.wui-glow` to any container; no extra component or DOM is needed. `web-ui-layout`'s
112
+ `header-glow` and collapse's peek edge use the same stylesheet.
113
+
114
+ ```html
115
+ <div class="wui-glow">...</div>
116
+ ```
117
+
118
+ - Both the gradient and the blur are background layers; content always sits above them. The container
119
+ needs a box size. `.wui-glow` only adds `position: relative` when the host has no other `position`, and
120
+ adds `isolation: isolate`.
121
+ - By default it lays a `--wui-color-page` gradient from the top edge down, then overlays `blur(4px)`; the
122
+ blurred layer extends 24px below the container before fading out. `overflow: hidden` on the container or
123
+ an ancestor clips that tail.
124
+ - On an opaque host the gradient still shows above its background, but the blur cannot sample what is behind
125
+ the host — it only blurs the host's own flat colour. Keep the host surface translucent for a frosted look.
126
+
127
+ | token | default | description |
128
+ | ------------------------------- | ----------------------------------------------- | ---------------------------------------------------- |
129
+ | `--wui-glow-color` | `var(--wui-color-page, #fff)` | Gradient start colour |
130
+ | `--wui-glow-gradient-direction` | `to bottom` | `linear-gradient` direction |
131
+ | `--wui-glow-gradient` | `linear-gradient` built from colour + direction | Full background-image; set `none` to disable |
132
+ | `--wui-glow-blur` | `4px` | `backdrop-filter` radius; set `0px` to disable |
133
+ | `--wui-glow-overhang` | `24px` | How far the blurred layer extends below the box |
134
+ | `--wui-glow-fade` | `36px` | Full-strength-to-transparent length; keep ≥ overhang |
135
+
67
136
  ## Vite
68
137
 
69
138
  `@greypan/web-ui/vite` exports `webUiOptimizeDeps`, the list of web-ui runtime dependencies an app has to merge
@@ -339,46 +408,46 @@ All form controls participate in native `FormData`, constraint validation, `form
339
408
 
340
409
  ## All Components
341
410
 
342
- Every component has its own doc page: API reference, behavior notes and interactive examples all live under [`docs/`](docs/). The table below is just the index.
343
-
344
- | Category | Component |
345
- | ---------------------- | --------------------------------------------------------- |
346
- | **Form Controls** | [`<web-ui-input>`](docs/input.md) |
347
- | | [`<web-ui-textarea>`](docs/textarea.md) |
348
- | | [`<web-ui-editable-text>`](docs/editable-text.md) |
349
- | | [`<web-ui-input-number>`](docs/input-number.md) |
350
- | | [`<web-ui-select>`](docs/select.md) |
351
- | | [`<web-ui-autocomplete>`](docs/autocomplete.md) |
352
- | | [`<web-ui-slider>`](docs/slider.md) |
353
- | | [`<web-ui-checkbox>`](docs/checkbox.md) |
354
- | | [`<web-ui-radio>`](docs/radio.md) |
355
- | | [`<web-ui-switch>`](docs/switch.md) |
356
- | | [`<web-ui-segmented>`](docs/segmented.md) |
357
- | | [`<web-ui-checkbox-group>`](docs/checkbox-group.md) |
358
- | | [`<web-ui-radio-group>`](docs/radio-group.md) |
359
- | **Buttons** | [`<web-ui-button>`](docs/button.md) |
360
- | | [`<web-ui-button-group>`](docs/button-group.md) |
361
- | **Overlay / Modal** | [`<web-ui-dialog>`](docs/dialog.md) |
362
- | | [`<web-ui-drawer>`](docs/drawer.md) |
363
- | | [`imagePreview()`](docs/image-preview.md) |
364
- | **In-flow Disclosure** | [`<web-ui-collapse>`](docs/collapse.md) |
365
- | **Floating** | [`<web-ui-popover>`](docs/popover.md) |
366
- | | [`<web-ui-tooltip>`](docs/tooltip.md) |
367
- | | [`<web-ui-context-menu>`](docs/context-menu.md) |
368
- | **Menu** | [`<web-ui-dropdown>`](docs/dropdown.md) |
369
- | | [`<web-ui-dropdown-item>`](docs/dropdown-item.md) |
370
- | | [`<web-ui-dropdown-divider>`](docs/dropdown-divider.md) |
371
- | | [`<web-ui-dropdown-header>`](docs/dropdown-header.md) |
372
- | **Data Display** | [`<web-ui-avatar>`](docs/avatar.md) |
373
- | | [`<web-ui-badge>`](docs/badge.md) |
374
- | | [`<web-ui-empty>`](docs/empty.md) |
375
- | | [`<web-ui-middle-ellipsis>`](docs/middle-ellipsis.md) |
376
- | | [`<web-ui-icon>`](docs/icon.md) |
377
- | | [`<web-ui-spinner>`](docs/spinner.md) |
378
- | **Layout & Utility** | [`<web-ui-layout>`](docs/layout.md) |
379
- | | [`<web-ui-back-top>`](docs/back-top.md) |
380
- | | [`<web-ui-svg-draw-lines>`](docs/svg-draw-lines.md) |
381
- | | [`<web-ui-theme>`](docs/theme.md) |
382
- | **Notification** | [`<web-ui-toast>`](docs/toast.md) |
383
- | **Sub-items** | [`<web-ui-option>`](docs/option.md) |
384
- | | [`<web-ui-segmented-trigger>`](docs/segmented-trigger.md) |
411
+ Every component has its own doc page: API reference, behavior notes and interactive examples all live under [`docs/`](./docs/). The table below is just the index.
412
+
413
+ | Category | Component |
414
+ | ---------------------- | ----------------------------------------------------------- |
415
+ | **Form Controls** | [`<web-ui-input>`](./docs/input.md) |
416
+ | | [`<web-ui-textarea>`](./docs/textarea.md) |
417
+ | | [`<web-ui-editable-text>`](./docs/editable-text.md) |
418
+ | | [`<web-ui-input-number>`](./docs/input-number.md) |
419
+ | | [`<web-ui-select>`](./docs/select.md) |
420
+ | | [`<web-ui-autocomplete>`](./docs/autocomplete.md) |
421
+ | | [`<web-ui-slider>`](./docs/slider.md) |
422
+ | | [`<web-ui-checkbox>`](./docs/checkbox.md) |
423
+ | | [`<web-ui-radio>`](./docs/radio.md) |
424
+ | | [`<web-ui-switch>`](./docs/switch.md) |
425
+ | | [`<web-ui-segmented>`](./docs/segmented.md) |
426
+ | | [`<web-ui-checkbox-group>`](./docs/checkbox-group.md) |
427
+ | | [`<web-ui-radio-group>`](./docs/radio-group.md) |
428
+ | **Buttons** | [`<web-ui-button>`](./docs/button.md) |
429
+ | | [`<web-ui-button-group>`](./docs/button-group.md) |
430
+ | **Overlay / Modal** | [`<web-ui-dialog>`](./docs/dialog.md) |
431
+ | | [`<web-ui-drawer>`](./docs/drawer.md) |
432
+ | | [`imagePreview()`](./docs/image-preview.md) |
433
+ | **In-flow Disclosure** | [`<web-ui-collapse>`](./docs/collapse.md) |
434
+ | **Floating** | [`<web-ui-popover>`](./docs/popover.md) |
435
+ | | [`<web-ui-tooltip>`](./docs/tooltip.md) |
436
+ | | [`<web-ui-context-menu>`](./docs/context-menu.md) |
437
+ | **Menu** | [`<web-ui-dropdown>`](./docs/dropdown.md) |
438
+ | | [`<web-ui-dropdown-item>`](./docs/dropdown-item.md) |
439
+ | | [`<web-ui-dropdown-divider>`](./docs/dropdown-divider.md) |
440
+ | | [`<web-ui-dropdown-header>`](./docs/dropdown-header.md) |
441
+ | **Data Display** | [`<web-ui-avatar>`](./docs/avatar.md) |
442
+ | | [`<web-ui-badge>`](./docs/badge.md) |
443
+ | | [`<web-ui-empty>`](./docs/empty.md) |
444
+ | | [`<web-ui-middle-ellipsis>`](./docs/middle-ellipsis.md) |
445
+ | | [`<web-ui-icon>`](./docs/icon.md) |
446
+ | | [`<web-ui-spinner>`](./docs/spinner.md) |
447
+ | **Layout & Utility** | [`<web-ui-layout>`](./docs/layout.md) |
448
+ | | [`<web-ui-back-top>`](./docs/back-top.md) |
449
+ | | [`<web-ui-svg-draw-lines>`](./docs/svg-draw-lines.md) |
450
+ | | [`<web-ui-theme>`](./docs/theme.md) |
451
+ | **Notification** | [`<web-ui-toast>`](./docs/toast.md) |
452
+ | **Sub-items** | [`<web-ui-option>`](./docs/option.md) |
453
+ | | [`<web-ui-segmented-trigger>`](./docs/segmented-trigger.md) |
@@ -1 +1 @@
1
- {"version":3,"file":"menu-portal.js","names":[],"sources":["../../src/assets/menu-portal.css?inline"],"sourcesContent":["/* 菜单面板:wui-glass 玻璃(背景/描边/阴影)由面板自身承担,随面板 opacity 与\n backdrop-filter 插值一起过渡(单层玻璃,见 overlay-motion.css)。\n 选择器用 .wui-menu-portal-overlay.wui-floating-panel(0,2,0)压制 .wui-glass\n (0,1,0):面板无自有 shadow root,直接挂在宿主 shadow(overlay root 的 \\3c style>\n 或 dialog 的 adopted stylesheets)里,若只用单类选择器,dialog 场景下宿主 adopted\n stylesheets 的 .wui-glass 会在层叠中晚于面板内联 \\3c style> 而胜出(position:relative\n 顶掉 fixed、背景/阴影变量回弱默认)。 */\n.wui-menu-portal-overlay.wui-floating-panel {\n --wui-internal-glass-shadow: var(--wui-shadow-panel, 0 3px 9px rgb(0 0 0 / 0.27));\n --wui-internal-duration-float-enter: var(--wui-duration-float-enter, 240ms);\n --wui-internal-duration-float-exit: var(--wui-duration-float-exit, 160ms);\n --wui-glass-corner-radius: var(--wui-radius-menu, 18px);\n\n /* 菜单族面板把环底色转 transparent。底色是环里唯一覆盖长边中段的一层(见 glass.css\n 的说明),而菜单面板宽远大于角半径 18px——按几何它只负责很短的一段,读出来却像\n 一条比四角更重的直边描边,边界感比四角强。转 transparent 后环只剩四段角弧,\n 斜向受光/背光光影(sheen + shade 的两枚对角 radial)完整保留,边界改由这两层\n 承担。handle 类玻璃面(switch/slider/segmented thumb)只在按压/拖拽态做同样处理:\n 它们的短边半径就是 thumb 尺寸的一半,长边长不过 3R,底色几乎不覆盖任何中段,\n 去掉它只去掉一层均匀灰 tint,不改变环的可见形状。 */\n --wui-color-glass-ring: transparent;\n user-select: none;\n\n position: fixed;\n z-index: var(--wui-layer-menu, 100);\n\n overflow: hidden;\n\n box-sizing: border-box;\n min-width: var(--wui-overlay-min-width, 200px);\n max-width: 90vw;\n max-height: 80vh;\n border-radius: var(--wui-radius-menu, 18px);\n\n color: var(--wui-color-text, #1b1b1b);\n\n /* 玻璃背景:面板自身 overflow:hidden 不裁自身的 box-shadow(box-shadow 不受\n 元素自身 overflow 影响)。 */\n background-color: var(--wui-color-surface-menu, rgb(250 250 250 / 0.76));\n\n & .wui-menu-scroll {\n overflow-y: auto;\n max-height: 80vh;\n }\n\n & .wui-menu-content {\n padding: var(--wui-space-1, 4px);\n }\n\n &.dropdown-overlay {\n & .wui-menu-scroll {\n max-height: 320px;\n }\n\n &[data-level]:not([data-level='0']) {\n z-index: var(--wui-layer-menu-nested, 110);\n }\n }\n\n &.context-submenu {\n z-index: var(--wui-layer-menu-nested, 110);\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"menu-portal.js","names":[],"sources":["../../src/assets/menu-portal.css?inline"],"sourcesContent":["/* menu panel:wui-glass 玻璃(背景/描边/阴影)由 panel 自身承担,随 panel opacity 与\n backdrop-filter 插值一起过渡(单层玻璃,见 overlay-motion.css)。\n 选择器用 .wui-menu-portal-overlay.wui-floating-panel(0,2,0)压制 .wui-glass\n (0,1,0):panel 无自有 shadow root,直接挂在宿主 shadow(overlay root 的 \\3c style>\n 或 dialog 的 adopted stylesheets)里,若只用单类选择器,dialog 场景下宿主 adopted\n stylesheets 的 .wui-glass 会在层叠中晚于 panel 内联 \\3c style> 而胜出(position:relative\n 顶掉 fixed、背景/阴影变量回弱默认)。 */\n.wui-menu-portal-overlay.wui-floating-panel {\n --wui-internal-glass-shadow: var(--wui-shadow-panel, 0 3px 9px rgb(0 0 0 / 0.27));\n --wui-internal-duration-float-enter: var(--wui-duration-float-enter, 240ms);\n --wui-internal-duration-float-exit: var(--wui-duration-float-exit, 160ms);\n --wui-glass-corner-radius: var(--wui-radius-menu, 18px);\n\n /* menu 族 panel 把环底色转 transparent。底色是环里唯一覆盖长边中段的一层(见 glass.css\n 的说明),而 menu panel 宽远大于角半径 18px——按几何它只负责很短的一段,读出来却像\n 一条比四角更重的直边描边,边界感比四角强。转 transparent 后环只剩四段角弧,\n 斜向受光/背光光影(sheen + shade 的两枚对角 radial)完整保留,边界改由这两层\n 承担。handle 类玻璃面(switch/slider/segmented thumb)只在按压/拖拽态做同样处理:\n 它们的短边半径就是 thumb 尺寸的一半,长边长不过 3R,底色几乎不覆盖任何中段,\n 去掉它只去掉一层均匀灰 tint,不改变环的可见形状。 */\n --wui-color-glass-ring: transparent;\n user-select: none;\n\n position: fixed;\n z-index: var(--wui-layer-menu, 100);\n\n overflow: hidden;\n\n box-sizing: border-box;\n min-width: var(--wui-overlay-min-width, 200px);\n max-width: 90vw;\n max-height: 80vh;\n border-radius: var(--wui-radius-menu, 18px);\n\n color: var(--wui-color-text, #1b1b1b);\n\n /* 玻璃背景:panel 自身 overflow:hidden 不裁自身的 box-shadow(box-shadow 不受\n 元素自身 overflow 影响)。 */\n background-color: var(--wui-color-surface-menu, rgb(250 250 250 / 0.76));\n\n & .wui-menu-scroll {\n overflow-y: auto;\n max-height: 80vh;\n }\n\n & .wui-menu-content {\n padding: var(--wui-space-1, 4px);\n }\n\n &.dropdown-overlay {\n & .wui-menu-scroll {\n max-height: 320px;\n }\n\n &[data-level]:not([data-level='0']) {\n z-index: var(--wui-layer-menu-nested, 110);\n }\n }\n\n &.context-submenu {\n z-index: var(--wui-layer-menu-nested, 110);\n }\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"modal-surface.js","names":[],"sources":["../../src/assets/modal-surface.css?inline"],"sourcesContent":["/*\n * 模态表面(dialog / drawer / image-preview 的 <dialog> 面板)的焦点环策略,集中一处。\n *\n * 1. `<dialog>` 壳不是可聚焦控件:面板里没有更优候选时,`showModal()` 会把焦点交给\n * dialog 本身,UA 会为它画一枚默认 ring。它是模态表面,内部控件各自保留 focus ring。\n *\n * 2. 面板的滚动区(`.desc` / `.wui-dialog-content` / `.wui-drawer-content`)同样不是\n * 可聚焦控件。Chromium 会把「可滚动的滚动容器」变成键盘可聚焦项\n * (keyboard-focusable scrollers),于是 dialog 的 focusing steps 会选中面板滚动区,\n * UA 为它画一枚默认蓝环(`outline: auto` + `-webkit-focus-ring-color`)。这一枚环\n * 与库的统一 ring(`outline: var(--wui-focus-ring-width) solid var(--wui-color-focus-ring)`)\n * 形态/颜色都不一致,是「dialog / drawer 打开后卡片上多出一圈蓝框」的来源:滚动区若是\n * 铺满卡片的(body 模式)且卡片自带 `overflow: hidden` + 圆角,这枚直角的 UA 环会被\n * 卡片裁成圆角矩形,看起来正贴着卡片外缘。\n *\n * 逐组件各抄一份正是「新增一个基于 `<dialog>` 的组件就漏掉抑制规则」的成因;新组件把本\n * 文件加进 `static styles` 即可。文档级 scrim(context-menu)不在这条链上——它自己注入\n * 样式表,按同样策略在 `scrim.css` 里就地收口。\n */\ndialog:focus,\ndialog:focus-visible,\ndialog :where(.desc, .wui-dialog-content, .wui-drawer-content):focus-visible {\n outline: none;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"modal-surface.js","names":[],"sources":["../../src/assets/modal-surface.css?inline"],"sourcesContent":["/*\n * 模态表面(dialog / drawer / image-preview 的 <dialog> panel)的焦点环策略,集中一处。\n *\n * 1. `<dialog>` 壳不是可聚焦控件:panel 里没有更优候选时,`showModal()` 会把焦点交给\n * dialog 本身,UA 会为它画一枚默认 ring。它是模态表面,内部控件各自保留 focus ring。\n *\n * 2. panel 的滚动区(`.desc` / `.wui-dialog-content` / `.wui-drawer-content`)同样不是\n * 可聚焦控件。Chromium 会把「可滚动的滚动容器」变成键盘可聚焦项\n * (keyboard-focusable scrollers),于是 dialog 的 focusing steps 会选中 panel 滚动区,\n * UA 为它画一枚默认蓝环(`outline: auto` + `-webkit-focus-ring-color`)。这一枚环\n * 与库的统一 ring(`outline: var(--wui-focus-ring-width) solid var(--wui-color-focus-ring)`)\n * 形态/颜色都不一致,是「dialog / drawer 打开后卡片上多出一圈蓝框」的来源:滚动区若是\n * 铺满卡片的(body 模式)且卡片自带 `overflow: hidden` + 圆角,这枚直角的 UA 环会被\n * 卡片裁成圆角矩形,看起来正贴着卡片外缘。\n *\n * 逐组件各抄一份正是「新增一个基于 `<dialog>` 的组件就漏掉抑制规则」的成因;新组件把本\n * 文件加进 `static styles` 即可。文档级 scrim(context-menu)不在这条链上——它自己注入\n * 样式表,按同样策略在 `scrim.css` 里就地收口。\n */\ndialog:focus,\ndialog:focus-visible,\ndialog :where(.desc, .wui-dialog-content, .wui-drawer-content):focus-visible {\n outline: none;\n}\n"],"mappings":""}
@@ -1,5 +1,5 @@
1
1
  //#region src/assets/overlay-motion.css?inline
2
- var e = ".wui-floating-panel{transform-origin:var(--wui-internal-overlay-transform-origin,center);opacity:1;-webkit-backdrop-filter:blur(4px) saturate(160%) brightness(var(--wui-glass-brightness,1.06));backdrop-filter:blur(4px) saturate(160%) brightness(var(--wui-glass-brightness,1.06));transition:opacity var(--wui-internal-duration-float-enter,var(--wui-duration-float-enter,.24s)) var(--wui-ease-float,cubic-bezier(.4, .38, .2, 1)), -webkit-backdrop-filter var(--wui-internal-duration-float-enter,var(--wui-duration-float-enter,.24s)) var(--wui-ease-float,cubic-bezier(.4, .38, .2, 1)), backdrop-filter var(--wui-internal-duration-float-enter,var(--wui-duration-float-enter,.24s)) var(--wui-ease-float,cubic-bezier(.4, .38, .2, 1)), transform var(--wui-internal-duration-float-enter,var(--wui-duration-float-enter,.24s)) var(--wui-ease-float,cubic-bezier(.4, .38, .2, 1));transform:scale(1)}.wui-floating-panel[data-wui-presence=entering],.wui-floating-panel[data-wui-presence=closing]{transform:scale(var(--wui-scale-enter,.9));opacity:0;-webkit-backdrop-filter:blur(0) saturate(160%) brightness(var(--wui-glass-brightness,1.06));backdrop-filter:blur(0) saturate(160%) brightness(var(--wui-glass-brightness,1.06))}.wui-floating-panel[data-wui-presence=closing]{pointer-events:none;transition-duration:var(--wui-internal-duration-float-exit,var(--wui-duration-float-exit,.16s))}@media (prefers-reduced-motion:reduce){.wui-floating-panel,.wui-floating-panel[data-wui-presence=entering],.wui-floating-panel[data-wui-presence=closing]{transition-duration:.12s;transform:none}}";
2
+ var e = ".wui-floating-panel{transform-origin:var(--wui-internal-overlay-transform-origin,center);opacity:1;-webkit-backdrop-filter:blur(var(--wui-glass-blur,4px)) saturate(var(--wui-glass-saturation,160%)) brightness(var(--wui-glass-brightness,1.06));backdrop-filter:blur(var(--wui-glass-blur,4px)) saturate(var(--wui-glass-saturation,160%)) brightness(var(--wui-glass-brightness,1.06));transition:opacity var(--wui-internal-duration-float-enter,var(--wui-duration-float-enter,.24s)) var(--wui-ease-float,cubic-bezier(.4, .38, .2, 1)), -webkit-backdrop-filter var(--wui-internal-duration-float-enter,var(--wui-duration-float-enter,.24s)) var(--wui-ease-float,cubic-bezier(.4, .38, .2, 1)), backdrop-filter var(--wui-internal-duration-float-enter,var(--wui-duration-float-enter,.24s)) var(--wui-ease-float,cubic-bezier(.4, .38, .2, 1)), transform var(--wui-internal-duration-float-enter,var(--wui-duration-float-enter,.24s)) var(--wui-ease-float,cubic-bezier(.4, .38, .2, 1));transform:scale(1)}.wui-floating-panel[data-wui-presence=entering],.wui-floating-panel[data-wui-presence=closing]{transform:scale(var(--wui-scale-enter,.9));opacity:0;-webkit-backdrop-filter:blur(0) saturate(var(--wui-glass-saturation,160%)) brightness(var(--wui-glass-brightness,1.06));backdrop-filter:blur(0) saturate(var(--wui-glass-saturation,160%)) brightness(var(--wui-glass-brightness,1.06))}.wui-floating-panel[data-wui-presence=closing]{pointer-events:none;transition-duration:var(--wui-internal-duration-float-exit,var(--wui-duration-float-exit,.16s))}@media (prefers-reduced-motion:reduce){.wui-floating-panel,.wui-floating-panel[data-wui-presence=entering],.wui-floating-panel[data-wui-presence=closing]{transition-duration:.12s;transform:none}}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"overlay-motion.js","names":[],"sources":["../../src/assets/overlay-motion.css?inline"],"sourcesContent":["/*\n * 浮层面板共享动效(单层玻璃)。\n *\n * backdrop-filter 的 blur(0px) ↔ blur(4px) 在 Chrome/Safari 均平滑插值(Manager\n * 双引擎实测,Safari 逐帧采样 blur 值连续),当年「生硬跳变」的根因是 none↔blur\n * 不可插值,而不是 backdrop-filter 不可动画。因此面板自身直接承担玻璃:背景、\n * 阴影与 backdrop-filter 都在面板元素上(wui-glass 类也回面板),打开/关闭时\n * opacity 与 backdrop-filter 同步过渡,无需双层结构——双层带来的全部层间问题\n * (变白、关闭残影、双重模糊、阴影作用域承接)一并消失。\n */\n\n.wui-floating-panel {\n transform-origin: var(--wui-internal-overlay-transform-origin, center);\n transform: scale(1);\n\n opacity: 1;\n\n /* 玻璃由面板自身承担(wui-glass 提供背景/描边/阴影)。打开目标态 blur(4px),\n entering/closing 切到 blur(0px) 作为插值起点——blur(0px) 与 blur(4px) 平滑过渡\n (none↔blur 不可插值才是当年生硬跳变的根因)。 */\n backdrop-filter: blur(4px) saturate(160%) brightness(var(--wui-glass-brightness, 1.06));\n\n /* transition 列表需手写 -webkit-backdrop-filter:lightningcss 不会在 transition\n value 内追加 -webkit 项,iOS 16.4 上 blur 过渡依赖它(属性前缀会自动生成)。\n 缓动取 --wui-ease-float:--wui-ease-enter 会在开局就冲到 85% 进度,锚定面板的展开\n 需要可读的过程。 */\n transition:\n opacity var(--wui-internal-duration-float-enter, var(--wui-duration-float-enter, 240ms))\n var(--wui-ease-float, cubic-bezier(0.4, 0.38, 0.2, 1)),\n -webkit-backdrop-filter var(--wui-internal-duration-float-enter, var(--wui-duration-float-enter, 240ms))\n var(--wui-ease-float, cubic-bezier(0.4, 0.38, 0.2, 1)),\n backdrop-filter var(--wui-internal-duration-float-enter, var(--wui-duration-float-enter, 240ms))\n var(--wui-ease-float, cubic-bezier(0.4, 0.38, 0.2, 1)),\n transform var(--wui-internal-duration-float-enter, var(--wui-duration-float-enter, 240ms))\n var(--wui-ease-float, cubic-bezier(0.4, 0.38, 0.2, 1));\n}\n\n.wui-floating-panel[data-wui-presence='entering'],\n.wui-floating-panel[data-wui-presence='closing'] {\n transform: scale(var(--wui-scale-enter, 0.9));\n opacity: 0;\n backdrop-filter: blur(0) saturate(160%) brightness(var(--wui-glass-brightness, 1.06));\n}\n\n.wui-floating-panel[data-wui-presence='closing'] {\n pointer-events: none;\n transition-duration: var(--wui-internal-duration-float-exit, var(--wui-duration-float-exit, 160ms));\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wui-floating-panel,\n .wui-floating-panel[data-wui-presence='entering'],\n .wui-floating-panel[data-wui-presence='closing'] {\n transform: none;\n transition-duration: 120ms;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"overlay-motion.js","names":[],"sources":["../../src/assets/overlay-motion.css?inline"],"sourcesContent":["/*\n * overlay panel 共享动效(单层玻璃)。\n *\n * backdrop-filter 的 blur(0px) ↔ blur(4px) 在 Chrome/Safari 均平滑插值(Manager\n * 双引擎实测,Safari 逐帧采样 blur 值连续),当年「生硬跳变」的根因是 none↔blur\n * 不可插值,而不是 backdrop-filter 不可动画。因此 panel 自身直接承担玻璃:背景、\n * 阴影与 backdrop-filter 都在 panel 元素上(wui-glass 类也回 panel),打开/关闭时\n * opacity 与 backdrop-filter 同步过渡,无需双层结构——双层带来的全部层间问题\n * (变白、关闭残影、双重模糊、阴影作用域承接)一并消失。\n */\n\n.wui-floating-panel {\n transform-origin: var(--wui-internal-overlay-transform-origin, center);\n transform: scale(1);\n\n opacity: 1;\n\n /* 玻璃由 panel 自身承担(wui-glass 提供背景/描边/阴影)。打开目标态 blur(4px),\n entering/closing 切到 blur(0px) 作为插值起点——blur(0px) 与 blur(4px) 平滑过渡\n (none↔blur 不可插值才是当年生硬跳变的根因)。 */\n backdrop-filter: blur(var(--wui-glass-blur, 4px)) saturate(var(--wui-glass-saturation, 160%))\n brightness(var(--wui-glass-brightness, 1.06));\n\n /* transition 列表需手写 -webkit-backdrop-filter:lightningcss 不会在 transition\n value 内追加 -webkit 项,iOS 16.4 上 blur 过渡依赖它(属性前缀会自动生成)。\n 缓动取 --wui-ease-float:--wui-ease-enter 会在开局就冲到 85% 进度,锚定 panel 的展开\n 需要可读的过程。 */\n transition:\n opacity var(--wui-internal-duration-float-enter, var(--wui-duration-float-enter, 240ms))\n var(--wui-ease-float, cubic-bezier(0.4, 0.38, 0.2, 1)),\n -webkit-backdrop-filter var(--wui-internal-duration-float-enter, var(--wui-duration-float-enter, 240ms))\n var(--wui-ease-float, cubic-bezier(0.4, 0.38, 0.2, 1)),\n backdrop-filter var(--wui-internal-duration-float-enter, var(--wui-duration-float-enter, 240ms))\n var(--wui-ease-float, cubic-bezier(0.4, 0.38, 0.2, 1)),\n transform var(--wui-internal-duration-float-enter, var(--wui-duration-float-enter, 240ms))\n var(--wui-ease-float, cubic-bezier(0.4, 0.38, 0.2, 1));\n}\n\n.wui-floating-panel[data-wui-presence='entering'],\n.wui-floating-panel[data-wui-presence='closing'] {\n transform: scale(var(--wui-scale-enter, 0.9));\n opacity: 0;\n backdrop-filter: blur(0) saturate(var(--wui-glass-saturation, 160%)) brightness(var(--wui-glass-brightness, 1.06));\n}\n\n.wui-floating-panel[data-wui-presence='closing'] {\n pointer-events: none;\n transition-duration: var(--wui-internal-duration-float-exit, var(--wui-duration-float-exit, 160ms));\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wui-floating-panel,\n .wui-floating-panel[data-wui-presence='entering'],\n .wui-floating-panel[data-wui-presence='closing'] {\n transform: none;\n transition-duration: 120ms;\n }\n}\n"],"mappings":""}
@@ -1,5 +1,5 @@
1
1
  //#region src/assets/selection-control.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{cursor:default;vertical-align:middle;align-items:center;display:inline-flex}:host([disabled]){cursor:not-allowed}:where(.wui-radio,.wui-checkbox){cursor:inherit;-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}:where(.wui-radio,.wui-checkbox):focus-visible{border-radius:var(--wui-radius-control,calc(infinity * 1px));outline:var(--wui-focus-ring-width,3px) solid var(--wui-color-focus-ring,color-mix(in srgb, var(--wui-color-accent,#08f) 40%, transparent));outline-offset:2px}:where(.wui-radio.is-label-empty,.wui-checkbox.is-label-empty){gap:0}:host([data-wui-pointer-focus]) :where(.wui-radio,.wui-checkbox):focus-visible{outline-color:#0000}:where(.wui-radio.is-disabled,.wui-checkbox.is-disabled){cursor:not-allowed;color:var(--wui-color-text-secondary,#6a6a6a);opacity:.4}:where(.wui-radio-circle,.wui-checkbox-box){isolation:isolate;width:var(--wui-selection-control-size,18px);height:var(--wui-selection-control-size,18px);background-color:var(--wui-color-surface-control,#dfdfdf);transition:background-color var(--wui-duration-trigger,.16s) ease;flex-shrink:0;justify-content:center;align-items:center;display:flex;position:relative}:where(.wui-radio-circle,.wui-checkbox-box):before{content:\"\";z-index:-1;border-radius:inherit;position:absolute;inset:0}:where(.wui-radio-label,.wui-checkbox-label){pointer-events:none}@media (hover:hover) and (pointer:fine){:where(.wui-radio,.wui-checkbox):hover:not(.is-disabled,.is-checked) :where(.wui-radio-circle,.wui-checkbox-box):before{background-color:color-mix(in srgb, var(--wui-color-text,#1b1b1b) 6%, transparent)}}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{cursor:default;vertical-align:middle;align-items:center;display:inline-flex}:host([disabled]){cursor:not-allowed}:where(.wui-radio,.wui-checkbox){cursor:inherit;-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}:where(.wui-radio,.wui-checkbox):focus-visible{border-radius:var(--wui-radius-control,calc(infinity * 1px));outline:var(--wui-focus-ring-width,3px) solid var(--wui-color-focus-ring,color-mix(in srgb, var(--wui-color-accent,#0071e3) 40%, transparent));outline-offset:2px}:where(.wui-radio.is-label-empty,.wui-checkbox.is-label-empty){gap:0}:host([data-wui-pointer-focus]) :where(.wui-radio,.wui-checkbox):focus-visible{outline-color:#0000}:where(.wui-radio.is-disabled,.wui-checkbox.is-disabled){cursor:not-allowed;color:var(--wui-color-text-secondary,#6a6a6a);opacity:.4}:where(.wui-radio-circle,.wui-checkbox-box){isolation:isolate;width:var(--wui-selection-control-size,18px);height:var(--wui-selection-control-size,18px);background-color:var(--wui-color-surface-control,#dfdfdf);transition:background-color var(--wui-duration-trigger,.16s) ease;flex-shrink:0;justify-content:center;align-items:center;display:flex;position:relative}:where(.wui-radio-circle,.wui-checkbox-box):before{content:\"\";z-index:-1;border-radius:inherit;position:absolute;inset:0}:where(.wui-radio-label,.wui-checkbox-label){pointer-events:none}@media (hover:hover) and (pointer:fine){:where(.wui-radio,.wui-checkbox):hover:not(.is-disabled,.is-checked) :where(.wui-radio-circle,.wui-checkbox-box):before{background-color:color-mix(in srgb, var(--wui-color-text,#1b1b1b) 6%, transparent)}}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"selection-control.js","names":[],"sources":["../../src/assets/selection-control.css?inline"],"sourcesContent":["/*\n * radio / checkbox 共享外壳。\n *\n * 指示器只有 18px。宿主一旦走 inline-block,页面行高会在宿主内生成匿名行盒,把盒子撑到\n * 行高(Tailwind preflight 下是 24px),且多出的空隙落在哪一侧取决于内部基线落点,radio 与\n * checkbox 因此一个贴顶一个贴底。改成 inline-flex 后宿主高度由内容决定,行高不再参与,\n * 与相邻文字的对齐交给 vertical-align 显式声明。\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n cursor: default;\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\n/* :where() 保持零特异性,组件级配置(圆角、选中色、内部图形)始终覆盖共享层。 */\n:where(.wui-radio, .wui-checkbox) {\n cursor: inherit;\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: var(--wui-radius-control, calc(infinity * 1px));\n outline: var(--wui-focus-ring-width, 3px) solid\n var(--wui-color-focus-ring, color-mix(in srgb, var(--wui-color-accent, #08f) 40%, transparent));\n outline-offset: 2px;\n }\n}\n\n/*\n * 标签没有可渲染内容时把间距一并收掉。gap 只认「这里有个 flex item」,不认它有没有宽度,所以空槽位\n * 或只挂了一个视觉隐藏的无障碍名时,指示器右边照样多出这一段;判据见 LabelEmptinessController。\n */\n:where(.wui-radio.is-label-empty, .wui-checkbox.is-label-empty) {\n gap: 0;\n}\n\n:host([data-wui-pointer-focus]) :where(.wui-radio, .wui-checkbox):focus-visible {\n outline-color: transparent;\n}\n\n:where(.wui-radio.is-disabled, .wui-checkbox.is-disabled) {\n cursor: not-allowed;\n color: var(--wui-color-text-secondary, #6a6a6a);\n opacity: 0.4;\n}\n\n/*\n * 指示器底色取控件档。surface-raised 在深色下(#2c2c2e)离页面底色(#242628)只有 8 个\n * 亮度点,未选中时几乎看不出有一个圆/方框;surface-control 才是主题里「控件自己的底」\n * 那一档(中性按钮同档),深色比页面高 22 个亮度点,浅色下也从近白的 #f2f2f7 变成可读的 #dfdfdf。\n */\n:where(.wui-radio-circle, .wui-checkbox-box) {\n isolation: isolate;\n position: relative;\n\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: var(--wui-selection-control-size, 18px);\n height: var(--wui-selection-control-size, 18px);\n\n background-color: var(--wui-color-surface-control, #dfdfdf);\n\n transition: background-color var(--wui-duration-trigger, 160ms) ease;\n}\n\n/*\n * 状态层走覆盖层,不占用指示器自己的 background-color:同一个属性没法一半过渡一半即时,\n * 而这里要的是 hover 当帧切换、选中态的 accent 按 --wui-duration-trigger 淡入淡出。\n * z-index: -1 配父级 isolation 把覆盖层夹在控件底与圆点/勾之间,半径跟着指示器走。\n */\n:where(.wui-radio-circle, .wui-checkbox-box)::before {\n content: '';\n\n position: absolute;\n z-index: -1;\n inset: 0;\n\n border-radius: inherit;\n}\n\n:where(.wui-radio-label, .wui-checkbox-label) {\n pointer-events: none;\n}\n\n/*\n * 未激活态的 hover 状态层。用半透明色而不是混进控件底:覆盖层本就压在不透明的控件底上,\n * 合成结果与 color-mix(text 6%, surface-control) 一致,深色档同样成立。\n * 标签文字带 pointer-events: none,命中落回 label 自身,所以整条触发区(含右侧文字)\n * 的 hover 都会作用到指示器。hover 只在真正的指针设备上生效,避免触屏留态。\n */\n@media (hover: hover) and (pointer: fine) {\n :where(.wui-radio, .wui-checkbox):hover:not(.is-disabled, .is-checked)\n :where(.wui-radio-circle, .wui-checkbox-box)::before {\n background-color: color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, transparent);\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"selection-control.js","names":[],"sources":["../../src/assets/selection-control.css?inline"],"sourcesContent":["/*\n * radio / checkbox 共享外壳。\n *\n * indicator 只有 18px。宿主一旦走 inline-block,页面行高会在宿主内生成匿名行盒,把盒子撑到\n * 行高(Tailwind preflight 下是 24px),且多出的空隙落在哪一侧取决于内部基线落点,radio 与\n * checkbox 因此一个贴顶一个贴底。改成 inline-flex 后宿主高度由内容决定,行高不再参与,\n * 与相邻文字的对齐交给 vertical-align 显式声明。\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n cursor: default;\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\n/* :where() 保持零特异性,组件级配置(圆角、选中色、内部图形)始终覆盖共享层。 */\n:where(.wui-radio, .wui-checkbox) {\n cursor: inherit;\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: var(--wui-radius-control, calc(infinity * 1px));\n outline: var(--wui-focus-ring-width, 3px) solid\n var(--wui-color-focus-ring, color-mix(in srgb, var(--wui-color-accent, #0071e3) 40%, transparent));\n outline-offset: 2px;\n }\n}\n\n/*\n * label 没有可渲染内容时把间距一并收掉。gap 只认「这里有个 flex item」,不认它有没有宽度,所以空槽位\n * 或只挂了一个视觉隐藏的无障碍名时,indicator 右边照样多出这一段;判据见 LabelEmptinessController。\n */\n:where(.wui-radio.is-label-empty, .wui-checkbox.is-label-empty) {\n gap: 0;\n}\n\n:host([data-wui-pointer-focus]) :where(.wui-radio, .wui-checkbox):focus-visible {\n outline-color: transparent;\n}\n\n:where(.wui-radio.is-disabled, .wui-checkbox.is-disabled) {\n cursor: not-allowed;\n color: var(--wui-color-text-secondary, #6a6a6a);\n opacity: 0.4;\n}\n\n/*\n * indicator 底色取控件档。surface-raised 在深色下(#2c2c2e)离页面底色(#242628)只有 8 个\n * 亮度点,未选中时几乎看不出有一个圆/方框;surface-control 才是主题里「控件自己的底」\n * 那一档(中性 button 同档),深色比页面高 22 个亮度点,浅色下也从近白的 #f2f2f7 变成可读的 #dfdfdf。\n */\n:where(.wui-radio-circle, .wui-checkbox-box) {\n isolation: isolate;\n position: relative;\n\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: var(--wui-selection-control-size, 18px);\n height: var(--wui-selection-control-size, 18px);\n\n background-color: var(--wui-color-surface-control, #dfdfdf);\n\n transition: background-color var(--wui-duration-trigger, 160ms) ease;\n}\n\n/*\n * 状态层走覆盖层,不占用 indicator 自己的 background-color:同一个属性没法一半过渡一半即时,\n * 而这里要的是 hover 当帧切换、选中态的 accent 按 --wui-duration-trigger 淡入淡出。\n * z-index: -1 配父级 isolation 把覆盖层夹在控件底与圆点/勾之间,半径跟着 indicator 走。\n */\n:where(.wui-radio-circle, .wui-checkbox-box)::before {\n content: '';\n\n position: absolute;\n z-index: -1;\n inset: 0;\n\n border-radius: inherit;\n}\n\n:where(.wui-radio-label, .wui-checkbox-label) {\n pointer-events: none;\n}\n\n/*\n * 未激活态的 hover 状态层。用半透明色而不是混进控件底:覆盖层本就压在不透明的控件底上,\n * 合成结果与 color-mix(text 6%, surface-control) 一致,深色档同样成立。\n * label 文字带 pointer-events: none,命中落回交互元素自身,所以整条触发区(含右侧文字)\n * 的 hover 都会作用到 indicator。hover 只在真正的指针设备上生效,避免触屏留态。\n */\n@media (hover: hover) and (pointer: fine) {\n :where(.wui-radio, .wui-checkbox):hover:not(.is-disabled, .is-checked)\n :where(.wui-radio-circle, .wui-checkbox-box)::before {\n background-color: color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, transparent);\n }\n}\n"],"mappings":""}
@@ -0,0 +1,6 @@
1
+ //#region src/classes/glass.css?inline
2
+ var e = ":where(.wui-glass){position:relative}.wui-glass{--wui-internal-glass-shadow:var(--wui-shadow-glass,0 0 1px #00000005, 0 0 8px #00000008, 0 2px 16px #00000006, 0 8px 32px #00000004);background-color:var(--wui-color-surface-glass,#fafafa57);-webkit-backdrop-filter:blur(var(--wui-glass-blur,4px)) saturate(var(--wui-glass-saturation,160%)) brightness(var(--wui-glass-brightness,1.06));backdrop-filter:blur(var(--wui-glass-blur,4px)) saturate(var(--wui-glass-saturation,160%)) brightness(var(--wui-glass-brightness,1.06));box-shadow:inset 0 0 0 .5px color-mix(in srgb, var(--wui-color-glass-highlight,#ffffffe6) 38%, transparent), inset 0 1px .5px color-mix(in srgb, var(--wui-color-glass-highlight,#ffffffe6) 52%, transparent), inset 0 -.5px 1px #00000008, var(--wui-internal-glass-shadow,var(--wui-shadow-glass,0 0 1px #00000005, 0 0 8px #00000008, 0 2px 16px #00000006, 0 8px 32px #00000004));background-clip:padding-box;border:none}.wui-glass:before{pointer-events:none;content:\"\";border-radius:inherit;background-color:var(--wui-color-glass-ring,#0000000d);background-image:radial-gradient(var(--wui-glass-corner-radius,32px) at 100% 0, var(--wui-color-glass-ring-shade,#00000008), transparent), radial-gradient(var(--wui-glass-corner-radius,32px) at 0 100%, var(--wui-color-glass-ring-shade,#00000008), transparent), radial-gradient(calc(var(--wui-glass-corner-radius,32px) * 2) at 0 0, var(--wui-color-glass-ring-sheen,#ffffff80), transparent), radial-gradient(calc(var(--wui-glass-corner-radius,32px) * 2) at 100% 100%, var(--wui-color-glass-ring-sheen,#ffffff80), transparent);-webkit-mask-composite:xor;-webkit-mask-source-type:auto,auto;padding:1px;position:absolute;inset:0;-webkit-mask-image:linear-gradient(#000 0 0),linear-gradient(#000 0 0);mask-image:linear-gradient(#000 0 0),linear-gradient(#000 0 0);-webkit-mask-position:0 0,0 0;mask-position:0 0,0 0;-webkit-mask-size:auto,auto;mask-size:auto,auto;-webkit-mask-repeat:repeat,repeat;mask-repeat:repeat,repeat;-webkit-mask-clip:content-box,border-box;mask-clip:content-box,border-box;-webkit-mask-origin:content-box,border-box;mask-origin:content-box,border-box;-webkit-mask-composite:xor;mask-composite:exclude;-webkit-mask-source-type:auto,auto;mask-mode:match-source,match-source}";
3
+ //#endregion
4
+ export { e as default };
5
+
6
+ //# sourceMappingURL=glass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glass.js","names":[],"sources":["../../src/classes/glass.css?inline"],"sourcesContent":["/* 只在宿主没有其他 position 时补定位,避免盖掉消费方的绝对/固定定位。 */\n:where(.wui-glass) {\n position: relative;\n}\n\n.wui-glass {\n /*\n * 内部阴影变量在 glass 元素上自声明默认值,切断从祖先 glass 容器(drawer/dialog\n * body 等声明了 overlay 阴影的元素)沿 flattened tree 继承进 slotted 内容的\n * 通道;各组件在自身元素上的同变量配置(特异性/源顺序恒胜出)不受影响。\n */\n --wui-internal-glass-shadow: var(\n --wui-shadow-glass,\n 0 0 1px rgb(0 0 0 / 0.02),\n 0 0 8px rgb(0 0 0 / 0.03),\n 0 2px 16px rgb(0 0 0 / 0.025),\n 0 8px 32px rgb(0 0 0 / 0.015)\n );\n\n border: none;\n\n background-color: var(--wui-color-surface-glass, rgb(250 250 250 / 0.34));\n background-clip: padding-box;\n\n /* Safari 16.4 只支持带 -webkit- 前缀的 backdrop-filter(无前缀 18 才支持);\n 前缀由 lightningcss 按 ?inline 管线默认 targets(含 ios16.4)自动生成,无需手写。 */\n backdrop-filter: blur(var(--wui-glass-blur, 4px)) saturate(var(--wui-glass-saturation, 160%))\n brightness(var(--wui-glass-brightness, 1.06));\n box-shadow:\n inset 0 0 0 0.5px color-mix(in srgb, var(--wui-color-glass-highlight, rgb(255 255 255 / 0.9)) 38%, transparent),\n inset 0 1px 0.5px color-mix(in srgb, var(--wui-color-glass-highlight, rgb(255 255 255 / 0.9)) 52%, transparent),\n inset 0 -0.5px 1px rgb(0 0 0 / 0.03),\n var(\n --wui-internal-glass-shadow,\n var(\n --wui-shadow-glass,\n 0 0 1px rgb(0 0 0 / 0.02),\n 0 0 8px rgb(0 0 0 / 0.03),\n 0 2px 16px rgb(0 0 0 / 0.025),\n 0 8px 32px rgb(0 0 0 / 0.015)\n )\n );\n}\n\n/*\n * 玻璃描边环:底色铺满整圈,其上叠两枚 sheen→transparent radial 作左上/右下受光\n * 光泽,再叠两枚 shade→transparent radial(置于最上层)压暗右上/左下背光角,形成\n * 对角光影的玻璃立体感。\n *\n * 底色(--wui-color-glass-ring)不是可选项:四枚 radial 全部锚定角点、半径固定\n * (R = --wui-glass-corner-radius,sheen 用 2R、shade 用 R),一条边只有长过约 3R\n * 才有一段落在所有 radial 之外。底色是唯一覆盖那一段的一层,也是圆角弧段(如 pill\n * 的半圆端)不发暗的原因。三枚 token 同属 ring 前缀,因为它们共同描述这一枚环,\n * 而非三个独立效果。\n *\n * 底色字面量取明色值 rgb(0 0 0 / 0.05) 而非 transparent:本文件其余玻璃 token 的\n * fallback 一律等于明色真值(surface-glass / brightness / highlight / sheen / shade),\n * token 缺省时(未挂 <web-ui-theme>,或 theme 未设 appearance —— 颜色 token 只定义在\n * [appearance] 三个选择器下)整套玻璃面就是明色观感,这一层没有理由例外。\n *\n * 渐变半径为 --wui-glass-corner-radius 的固定物理尺寸正圆——视觉覆盖范围不随元素\n * 宽高缩放(百分比方案在大 panel 上暗边过长、小控件上过弱),各组件用与自身\n * border-radius 同源的值覆盖该变量即可联动。\n *\n * 同源的 --wui-color-glass-highlight 不在此层:它是元素自身 box-shadow 的 inset\n * 高光,与本环无关。-webkit-mask-* 旧语法(含 mask-composite:xor)由 lightningcss\n * 按 targets 自动生成,无前缀 mask-composite 留给 Chrome 120+。\n */\n.wui-glass::before {\n pointer-events: none;\n content: '';\n\n position: absolute;\n inset: 0;\n\n padding: 1px;\n border-radius: inherit;\n\n background-color: var(--wui-color-glass-ring, rgb(0 0 0 / 0.05));\n background-image:\n radial-gradient(\n var(--wui-glass-corner-radius, 32px) at 100% 0,\n var(--wui-color-glass-ring-shade, rgb(0 0 0 / 0.03)),\n transparent\n ),\n radial-gradient(\n var(--wui-glass-corner-radius, 32px) at 0 100%,\n var(--wui-color-glass-ring-shade, rgb(0 0 0 / 0.03)),\n transparent\n ),\n radial-gradient(\n calc(var(--wui-glass-corner-radius, 32px) * 2) at 0 0,\n var(--wui-color-glass-ring-sheen, rgb(255 255 255 / 0.5)),\n transparent\n ),\n radial-gradient(\n calc(var(--wui-glass-corner-radius, 32px) * 2) at 100% 100%,\n var(--wui-color-glass-ring-sheen, rgb(255 255 255 / 0.5)),\n transparent\n );\n\n mask:\n linear-gradient(#000 0 0) content-box,\n linear-gradient(#000 0 0);\n mask-composite: exclude;\n}\n"],"mappings":""}
@@ -0,0 +1,6 @@
1
+ //#region src/classes/glow.css?inline
2
+ var e = ":where(.wui-glow){position:relative}.wui-glow{isolation:isolate}.wui-glow:before,.wui-glow:after{pointer-events:none;content:\"\";z-index:-1;border-radius:inherit;position:absolute;inset:0}.wui-glow:before{background:var(--wui-glow-gradient,linear-gradient(var(--wui-glow-gradient-direction,to bottom), var(--wui-glow-color,var(--wui-color-page,#fff)), transparent))}.wui-glow:after{inset:0 0 calc(-1 * var(--wui-glow-overhang,24px));-webkit-backdrop-filter:blur(var(--wui-glow-blur,4px));backdrop-filter:blur(var(--wui-glow-blur,4px));-webkit-mask-image:linear-gradient(to bottom, black 0, black calc(100% - var(--wui-glow-fade,36px)), transparent 100%);-webkit-mask-image:linear-gradient(to bottom, black 0, black calc(100% - var(--wui-glow-fade,36px)), transparent 100%);mask-image:linear-gradient(to bottom, black 0, black calc(100% - var(--wui-glow-fade,36px)), transparent 100%);-webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}";
3
+ //#endregion
4
+ export { e as default };
5
+
6
+ //# sourceMappingURL=glow.js.map