@remix-run/ui 0.0.0 → 0.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 (273) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -2
  3. package/dist/animation/animate-layout-mixin.d.ts +12 -0
  4. package/dist/animation/animate-layout-mixin.js +214 -0
  5. package/dist/animation/animate-layout-mixin.js.map +1 -0
  6. package/dist/animation/animate-mixins.d.ts +29 -0
  7. package/dist/animation/animate-mixins.js +235 -0
  8. package/dist/animation/animate-mixins.js.map +1 -0
  9. package/dist/animation/index.d.ts +6 -0
  10. package/dist/animation/index.js +5 -0
  11. package/dist/animation/index.js.map +1 -0
  12. package/dist/animation/spring.d.ts +75 -0
  13. package/dist/animation/spring.js +183 -0
  14. package/dist/animation/spring.js.map +1 -0
  15. package/dist/animation/tween.d.ts +70 -0
  16. package/dist/animation/tween.js +93 -0
  17. package/dist/animation/tween.js.map +1 -0
  18. package/dist/components/accordion/accordion.d.ts +92 -0
  19. package/dist/components/accordion/accordion.js +337 -0
  20. package/dist/components/accordion/accordion.js.map +1 -0
  21. package/dist/components/anchor/anchor.d.ts +13 -0
  22. package/dist/components/anchor/anchor.js +558 -0
  23. package/dist/components/anchor/anchor.js.map +1 -0
  24. package/dist/components/breadcrumbs/breadcrumbs.d.ts +11 -0
  25. package/dist/components/breadcrumbs/breadcrumbs.js +78 -0
  26. package/dist/components/breadcrumbs/breadcrumbs.js.map +1 -0
  27. package/dist/components/button/button.d.ts +23 -0
  28. package/dist/components/button/button.js +147 -0
  29. package/dist/components/button/button.js.map +1 -0
  30. package/dist/components/combobox/combobox.d.ts +101 -0
  31. package/dist/components/combobox/combobox.js +708 -0
  32. package/dist/components/combobox/combobox.js.map +1 -0
  33. package/dist/components/glyph/glyph.d.ts +14 -0
  34. package/dist/components/glyph/glyph.js +65 -0
  35. package/dist/components/glyph/glyph.js.map +1 -0
  36. package/dist/components/listbox/listbox.d.ts +67 -0
  37. package/dist/components/listbox/listbox.js +340 -0
  38. package/dist/components/listbox/listbox.js.map +1 -0
  39. package/dist/components/menu/hover-aim.d.ts +5 -0
  40. package/dist/components/menu/hover-aim.js +308 -0
  41. package/dist/components/menu/hover-aim.js.map +1 -0
  42. package/dist/components/menu/menu.d.ts +164 -0
  43. package/dist/components/menu/menu.js +1106 -0
  44. package/dist/components/menu/menu.js.map +1 -0
  45. package/dist/components/popover/popover.d.ts +35 -0
  46. package/dist/components/popover/popover.js +138 -0
  47. package/dist/components/popover/popover.js.map +1 -0
  48. package/dist/components/select/select.d.ts +67 -0
  49. package/dist/components/select/select.js +397 -0
  50. package/dist/components/select/select.js.map +1 -0
  51. package/dist/components/separator/separator.d.ts +2 -0
  52. package/dist/components/separator/separator.js +15 -0
  53. package/dist/components/separator/separator.js.map +1 -0
  54. package/dist/components/tabs/tabs.d.ts +78 -0
  55. package/dist/components/tabs/tabs.js +341 -0
  56. package/dist/components/tabs/tabs.js.map +1 -0
  57. package/dist/index.d.ts +28 -0
  58. package/dist/index.js +21 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/interactions/keydown/keydown.d.ts +1 -0
  61. package/dist/interactions/keydown/keydown.js +8 -0
  62. package/dist/interactions/keydown/keydown.js.map +1 -0
  63. package/dist/interactions/outside-click/outside-click-mixin.d.ts +2 -0
  64. package/dist/interactions/outside-click/outside-click-mixin.js +29 -0
  65. package/dist/interactions/outside-click/outside-click-mixin.js.map +1 -0
  66. package/dist/interactions/typeahead/typeahead-mixin.d.ts +8 -0
  67. package/dist/interactions/typeahead/typeahead-mixin.js +59 -0
  68. package/dist/interactions/typeahead/typeahead-mixin.js.map +1 -0
  69. package/dist/jsx-runtime.d.ts +2 -0
  70. package/dist/jsx-runtime.js +3 -0
  71. package/dist/jsx-runtime.js.map +1 -0
  72. package/dist/runtime/client-entries.d.ts +91 -0
  73. package/dist/runtime/client-entries.js +40 -0
  74. package/dist/runtime/client-entries.js.map +1 -0
  75. package/dist/runtime/component.d.ts +223 -0
  76. package/dist/runtime/component.js +152 -0
  77. package/dist/runtime/component.js.map +1 -0
  78. package/dist/runtime/create-element.d.ts +10 -0
  79. package/dist/runtime/create-element.js +29 -0
  80. package/dist/runtime/create-element.js.map +1 -0
  81. package/dist/runtime/diff-dom.d.ts +2 -0
  82. package/dist/runtime/diff-dom.js +364 -0
  83. package/dist/runtime/diff-dom.js.map +1 -0
  84. package/dist/runtime/diff-props.d.ts +9 -0
  85. package/dist/runtime/diff-props.js +195 -0
  86. package/dist/runtime/diff-props.js.map +1 -0
  87. package/dist/runtime/document-state.d.ts +11 -0
  88. package/dist/runtime/document-state.js +106 -0
  89. package/dist/runtime/document-state.js.map +1 -0
  90. package/dist/runtime/dom.d.ts +3189 -0
  91. package/dist/runtime/dom.js +2 -0
  92. package/dist/runtime/dom.js.map +1 -0
  93. package/dist/runtime/error-event.d.ts +20 -0
  94. package/dist/runtime/error-event.js +19 -0
  95. package/dist/runtime/error-event.js.map +1 -0
  96. package/dist/runtime/event-listeners.d.ts +50 -0
  97. package/dist/runtime/event-listeners.js +31 -0
  98. package/dist/runtime/event-listeners.js.map +1 -0
  99. package/dist/runtime/frame.d.ts +119 -0
  100. package/dist/runtime/frame.js +915 -0
  101. package/dist/runtime/frame.js.map +1 -0
  102. package/dist/runtime/invariant.d.ts +23 -0
  103. package/dist/runtime/invariant.js +33 -0
  104. package/dist/runtime/invariant.js.map +1 -0
  105. package/dist/runtime/jsx.d.ts +320 -0
  106. package/dist/runtime/jsx.js +31 -0
  107. package/dist/runtime/jsx.js.map +1 -0
  108. package/dist/runtime/mixins/attrs-mixin.d.ts +9 -0
  109. package/dist/runtime/mixins/attrs-mixin.js +23 -0
  110. package/dist/runtime/mixins/attrs-mixin.js.map +1 -0
  111. package/dist/runtime/mixins/link-mixin.d.ts +17 -0
  112. package/dist/runtime/mixins/link-mixin.js +101 -0
  113. package/dist/runtime/mixins/link-mixin.js.map +1 -0
  114. package/dist/runtime/mixins/mixin.d.ts +145 -0
  115. package/dist/runtime/mixins/mixin.js +570 -0
  116. package/dist/runtime/mixins/mixin.js.map +1 -0
  117. package/dist/runtime/mixins/on-mixin.d.ts +16 -0
  118. package/dist/runtime/mixins/on-mixin.js +49 -0
  119. package/dist/runtime/mixins/on-mixin.js.map +1 -0
  120. package/dist/runtime/mixins/ref-mixin.d.ts +9 -0
  121. package/dist/runtime/mixins/ref-mixin.js +21 -0
  122. package/dist/runtime/mixins/ref-mixin.js.map +1 -0
  123. package/dist/runtime/navigation.d.ts +22 -0
  124. package/dist/runtime/navigation.js +102 -0
  125. package/dist/runtime/navigation.js.map +1 -0
  126. package/dist/runtime/reconcile.d.ts +11 -0
  127. package/dist/runtime/reconcile.js +1240 -0
  128. package/dist/runtime/reconcile.js.map +1 -0
  129. package/dist/runtime/render.d.ts +54 -0
  130. package/dist/runtime/render.js +50 -0
  131. package/dist/runtime/render.js.map +1 -0
  132. package/dist/runtime/run.d.ts +45 -0
  133. package/dist/runtime/run.js +68 -0
  134. package/dist/runtime/run.js.map +1 -0
  135. package/dist/runtime/scheduler.d.ts +30 -0
  136. package/dist/runtime/scheduler.js +185 -0
  137. package/dist/runtime/scheduler.js.map +1 -0
  138. package/dist/runtime/svg-attributes.d.ts +5 -0
  139. package/dist/runtime/svg-attributes.js +124 -0
  140. package/dist/runtime/svg-attributes.js.map +1 -0
  141. package/dist/runtime/to-vnode.d.ts +3 -0
  142. package/dist/runtime/to-vnode.js +43 -0
  143. package/dist/runtime/to-vnode.js.map +1 -0
  144. package/dist/runtime/typed-event-target.d.ts +50 -0
  145. package/dist/runtime/typed-event-target.js +6 -0
  146. package/dist/runtime/typed-event-target.js.map +1 -0
  147. package/dist/runtime/vdom.d.ts +55 -0
  148. package/dist/runtime/vdom.js +198 -0
  149. package/dist/runtime/vdom.js.map +1 -0
  150. package/dist/runtime/vnode.d.ts +79 -0
  151. package/dist/runtime/vnode.js +38 -0
  152. package/dist/runtime/vnode.js.map +1 -0
  153. package/dist/server/stream.d.ts +57 -0
  154. package/dist/server/stream.js +1007 -0
  155. package/dist/server/stream.js.map +1 -0
  156. package/dist/style/css-mixin.d.ts +8 -0
  157. package/dist/style/css-mixin.js +54 -0
  158. package/dist/style/css-mixin.js.map +1 -0
  159. package/dist/style/index.d.ts +5 -0
  160. package/dist/style/index.js +4 -0
  161. package/dist/style/index.js.map +1 -0
  162. package/dist/style/style.d.ts +24 -0
  163. package/dist/style/style.js +269 -0
  164. package/dist/style/style.js.map +1 -0
  165. package/dist/style/stylesheet.d.ts +11 -0
  166. package/dist/style/stylesheet.js +174 -0
  167. package/dist/style/stylesheet.js.map +1 -0
  168. package/dist/test.d.ts +2 -0
  169. package/dist/test.js +2 -0
  170. package/dist/test.js.map +1 -0
  171. package/dist/theme/contract.d.ts +259 -0
  172. package/dist/theme/contract.js +131 -0
  173. package/dist/theme/contract.js.map +1 -0
  174. package/dist/theme/glyph-contract.d.ts +13 -0
  175. package/dist/theme/glyph-contract.js +34 -0
  176. package/dist/theme/glyph-contract.js.map +1 -0
  177. package/dist/theme/presets/rmx-01/glyphs.d.ts +2 -0
  178. package/dist/theme/presets/rmx-01/glyphs.js +252 -0
  179. package/dist/theme/presets/rmx-01/glyphs.js.map +1 -0
  180. package/dist/theme/presets/rmx-01/index.d.ts +2 -0
  181. package/dist/theme/presets/rmx-01/index.js +119 -0
  182. package/dist/theme/presets/rmx-01/index.js.map +1 -0
  183. package/dist/theme/runtime.d.ts +2 -0
  184. package/dist/theme/runtime.js +81 -0
  185. package/dist/theme/runtime.js.map +1 -0
  186. package/dist/theme/theme.d.ts +6 -0
  187. package/dist/theme/theme.js +5 -0
  188. package/dist/theme/theme.js.map +1 -0
  189. package/dist/utils/flash-attribute.d.ts +1 -0
  190. package/dist/utils/flash-attribute.js +11 -0
  191. package/dist/utils/flash-attribute.js.map +1 -0
  192. package/dist/utils/scroll-lock.d.ts +3 -0
  193. package/dist/utils/scroll-lock.js +69 -0
  194. package/dist/utils/scroll-lock.js.map +1 -0
  195. package/dist/utils/wait-for-css-transition.d.ts +1 -0
  196. package/dist/utils/wait-for-css-transition.js +58 -0
  197. package/dist/utils/wait-for-css-transition.js.map +1 -0
  198. package/dist/utils/wait.d.ts +1 -0
  199. package/dist/utils/wait.js +6 -0
  200. package/dist/utils/wait.js.map +1 -0
  201. package/package.json +125 -5
  202. package/src/animation/animate-layout-mixin.ts +266 -0
  203. package/src/animation/animate-mixins.ts +292 -0
  204. package/src/animation/index.ts +6 -0
  205. package/src/animation/spring.ts +299 -0
  206. package/src/animation/tween.ts +134 -0
  207. package/src/components/accordion/accordion.tsx +565 -0
  208. package/src/components/anchor/anchor.ts +904 -0
  209. package/src/components/breadcrumbs/breadcrumbs.tsx +124 -0
  210. package/src/components/button/README.md +44 -0
  211. package/src/components/button/button.tsx +188 -0
  212. package/src/components/combobox/README.md +145 -0
  213. package/src/components/combobox/combobox.tsx +1014 -0
  214. package/src/components/glyph/glyph.tsx +110 -0
  215. package/src/components/listbox/listbox.ts +447 -0
  216. package/src/components/menu/hover-aim.ts +428 -0
  217. package/src/components/menu/menu.tsx +1547 -0
  218. package/src/components/popover/README.md +122 -0
  219. package/src/components/popover/popover.ts +201 -0
  220. package/src/components/select/select.tsx +585 -0
  221. package/src/components/separator/separator.ts +19 -0
  222. package/src/components/tabs/README.md +105 -0
  223. package/src/components/tabs/tabs.tsx +499 -0
  224. package/src/index.ts +72 -0
  225. package/src/interactions/keydown/keydown.ts +14 -0
  226. package/src/interactions/outside-click/outside-click-mixin.ts +55 -0
  227. package/src/interactions/typeahead/typeahead-mixin.ts +89 -0
  228. package/src/jsx-runtime.ts +2 -0
  229. package/src/runtime/client-entries.ts +137 -0
  230. package/src/runtime/component.ts +402 -0
  231. package/src/runtime/create-element.ts +38 -0
  232. package/src/runtime/diff-dom.ts +404 -0
  233. package/src/runtime/diff-props.ts +209 -0
  234. package/src/runtime/document-state.ts +130 -0
  235. package/src/runtime/dom.ts +3971 -0
  236. package/src/runtime/error-event.ts +26 -0
  237. package/src/runtime/event-listeners.ts +171 -0
  238. package/src/runtime/frame.ts +1211 -0
  239. package/src/runtime/invariant.ts +31 -0
  240. package/src/runtime/jsx.ts +398 -0
  241. package/src/runtime/mixins/attrs-mixin.ts +35 -0
  242. package/src/runtime/mixins/link-mixin.ts +131 -0
  243. package/src/runtime/mixins/mixin.ts +908 -0
  244. package/src/runtime/mixins/on-mixin.ts +89 -0
  245. package/src/runtime/mixins/ref-mixin.ts +32 -0
  246. package/src/runtime/navigation.ts +136 -0
  247. package/src/runtime/reconcile.ts +1722 -0
  248. package/src/runtime/render.ts +101 -0
  249. package/src/runtime/run.ts +100 -0
  250. package/src/runtime/scheduler.ts +262 -0
  251. package/src/runtime/svg-attributes.ts +133 -0
  252. package/src/runtime/to-vnode.ts +50 -0
  253. package/src/runtime/typed-event-target.ts +67 -0
  254. package/src/runtime/vdom.ts +295 -0
  255. package/src/runtime/vnode.ts +137 -0
  256. package/src/server/stream.ts +1342 -0
  257. package/src/style/css-mixin.ts +82 -0
  258. package/src/style/index.ts +10 -0
  259. package/src/style/style.ts +312 -0
  260. package/src/style/stylesheet.ts +209 -0
  261. package/src/test/setup.ts +7 -0
  262. package/src/test/utils.ts +45 -0
  263. package/src/test.ts +2 -0
  264. package/src/theme/contract.ts +183 -0
  265. package/src/theme/glyph-contract.ts +57 -0
  266. package/src/theme/presets/rmx-01/glyphs.tsx +308 -0
  267. package/src/theme/presets/rmx-01/index.ts +121 -0
  268. package/src/theme/runtime.ts +116 -0
  269. package/src/theme/theme.ts +15 -0
  270. package/src/utils/flash-attribute.ts +11 -0
  271. package/src/utils/scroll-lock.ts +97 -0
  272. package/src/utils/wait-for-css-transition.ts +66 -0
  273. package/src/utils/wait.ts +5 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Use this when framework code is incorrect, indicating an internal bug rather
3
+ * than application code error.
4
+ *
5
+ * @param assertion The value to check for truthiness
6
+ * @param message Optional message to include in the error
7
+ */
8
+ export function invariant(assertion: any, message?: string): asserts assertion {
9
+ let prefix = 'Framework invariant'
10
+ if (assertion) return
11
+ throw new Error(message ? `${prefix}: ${message}` : prefix)
12
+ }
13
+
14
+ /**
15
+ * Use this when application logic is incorrect, indicating a developer error.
16
+ *
17
+ * Using ID-based warnings with external documentation links allows us to:
18
+ * - Update warning messages without releasing new versions
19
+ * - Avoid bloating the library with warning messages or complicating builds
20
+ * with prod/dev build/export shenanigans
21
+ * - Provide detailed troubleshooting guides and examples
22
+ *
23
+ * `id` is first so we can easily grep the codebase for ensure calls
24
+ *
25
+ * @param id The error ID for the documentation link
26
+ * @param assertion The value to check for truthiness
27
+ */
28
+ export function ensure(id: number, assertion: boolean): asserts assertion {
29
+ if (assertion) return
30
+ throw new Error(`REMIX_${id}: https://rmx.as/w/${id}`)
31
+ }
@@ -0,0 +1,398 @@
1
+ import type * as dom from './dom.d.ts'
2
+ import type { Handle, RenderFn } from './component.ts'
3
+
4
+ /**
5
+ * Any valid element type accepted by JSX or {@link import('./create-element.ts').createElement}.
6
+ * - `string` for host elements (e.g., 'div')
7
+ * - `Function` for user components
8
+ */
9
+ export type ElementType = string | Function
10
+
11
+ /**
12
+ * Generic bag of props passed to elements/components.
13
+ * Consumers should define specific prop types on their components; this is the
14
+ * renderer's normalized shape used throughout reconciler/SSR code.
15
+ */
16
+ export type ElementProps = Record<string, any>
17
+
18
+ /**
19
+ * A virtual element produced by JSX or {@link import('./create-element.ts').createElement}
20
+ * describing UI. Carries a `$rmx` brand used to distinguish it from plain objects at runtime.
21
+ */
22
+ export interface RemixElement {
23
+ /** Host tag or component function for the element. */
24
+ type: ElementType
25
+ /** Normalized props for the element. */
26
+ props: ElementProps
27
+ /** Optional reconciliation key. */
28
+ key?: any
29
+ /** Internal brand used to distinguish Remix elements at runtime. */
30
+ $rmx: true
31
+ }
32
+
33
+ /**
34
+ * Any single value Remix can render. Booleans render as empty text.
35
+ */
36
+ export type Renderable = RemixElement | string | number | bigint | boolean | null | undefined
37
+
38
+ /**
39
+ * Anything that Remix can render, including nested arrays of renderable values.
40
+ * This mirrors how JSX spreads children into arrays (e.g. when using `map`)
41
+ * and how our reconciler flattens children at runtime.
42
+ *
43
+ * Particularly useful for `props.children`.
44
+ *
45
+ * ```tsx
46
+ * function MyComponent({ children }: { children: RemixNode }) {}
47
+ * ```
48
+ */
49
+ export type RemixNode = Renderable | RemixNode[]
50
+
51
+ type PreviousMixDepth = [0, 0, 1, 2, 3, 4]
52
+ type FalsyMixValue = false | 0 | 0n | '' | null | undefined
53
+ type NullableMixValue<mix> = mix | FalsyMixValue
54
+ type MixLeaf<mix> = mix extends ReadonlyArray<infer descriptor> ? MixLeaf<descriptor> : mix
55
+ type NormalizeMixLeaf<mix> = Exclude<MixLeaf<mix>, FalsyMixValue>
56
+ type NestedMixValue<mix, depth extends number = 4> = depth extends 0
57
+ ? NullableMixValue<mix> | ReadonlyArray<NullableMixValue<mix>>
58
+ : NullableMixValue<mix> | ReadonlyArray<NestedMixValue<mix, PreviousMixDepth[depth]>>
59
+
60
+ type NormalizeMixProp<props> = props extends { mix?: infer mix }
61
+ ? Omit<props, 'mix'> & {
62
+ mix?: Array<NormalizeMixLeaf<mix>>
63
+ }
64
+ : props
65
+
66
+ type ExpandMixProp<props> = props extends { mix?: infer mix }
67
+ ? Omit<props, 'mix'> & {
68
+ mix?: NestedMixValue<NormalizeMixLeaf<mix>>
69
+ }
70
+ : props
71
+
72
+ type MixinElementType = ((
73
+ handle: { update(): Promise<AbortSignal> },
74
+ setup: unknown,
75
+ ) => (props: any) => RemixElement) & {
76
+ __rmxMixinElementType: string
77
+ }
78
+
79
+ type MergeComponentProps<handleProps, renderProps> = [handleProps] extends [Record<string, never>]
80
+ ? renderProps
81
+ : handleProps & renderProps
82
+
83
+ /**
84
+ * Get the props for a specific element type.
85
+ *
86
+ * @example
87
+ * interface MyButtonProps extends Props<"button"> {
88
+ * size: "sm" | "md" | "lg"
89
+ * }
90
+ */
91
+ export type Props<T extends keyof JSX.IntrinsicElements> = NormalizeMixProp<
92
+ JSX.IntrinsicElements[T]
93
+ >
94
+
95
+ /**
96
+ * Creates a Remix virtual element.
97
+ *
98
+ * @param type Host tag or component function.
99
+ * @param props Element props.
100
+ * @param key Optional reconciliation key.
101
+ * @returns A Remix virtual element.
102
+ */
103
+ export function jsx(type: ElementType, props: ElementProps, key?: string): RemixElement
104
+ export function jsx(type: ElementType, props: ElementProps, key?: string): RemixElement {
105
+ return { type, props: normalizeElementProps(props), key, $rmx: true }
106
+ }
107
+
108
+ export { jsx as jsxDEV, jsx as jsxs }
109
+
110
+ declare global {
111
+ namespace JSX {
112
+ export interface IntrinsicAttributes {
113
+ key?: any
114
+ }
115
+
116
+ type Element = RemixElement
117
+
118
+ type ElementType =
119
+ // host elements
120
+ | keyof IntrinsicElements
121
+ // Factory component
122
+ | ((handle: Handle<any, any>) => RenderFn<any>)
123
+ // Mixin element used internally by mixin render callbacks
124
+ | MixinElementType
125
+
126
+ type ElementChildrenAttribute = {
127
+ children: any
128
+ }
129
+
130
+ export interface ElementAttributesProperty {
131
+ props: any
132
+ }
133
+
134
+ type LibraryManagedAttributes<component, props> = component extends MixinElementType
135
+ ? ExpandMixProp<Parameters<ReturnType<component>>[0]>
136
+ : component extends (handle: Handle<infer P, any>) => RenderFn<infer R>
137
+ ? // It's a ComponentFactory - infer props from the handle
138
+ ExpandMixProp<MergeComponentProps<P, R>>
139
+ : component extends () => RenderFn<infer P>
140
+ ? ExpandMixProp<P>
141
+ : // Otherwise use props as-is (simple function component)
142
+ ExpandMixProp<props>
143
+
144
+ export interface IntrinsicSVGElements {
145
+ svg: dom.SVGProps<SVGSVGElement>
146
+ animate: dom.SVGProps<SVGAnimateElement>
147
+ circle: dom.SVGProps<SVGCircleElement>
148
+ animateMotion: dom.SVGProps<SVGAnimateMotionElement>
149
+ animateTransform: dom.SVGProps<SVGAnimateTransformElement>
150
+ clipPath: dom.SVGProps<SVGClipPathElement>
151
+ defs: dom.SVGProps<SVGDefsElement>
152
+ desc: dom.SVGProps<SVGDescElement>
153
+ ellipse: dom.SVGProps<SVGEllipseElement>
154
+ feBlend: dom.SVGProps<SVGFEBlendElement>
155
+ feColorMatrix: dom.SVGProps<SVGFEColorMatrixElement>
156
+ feComponentTransfer: dom.SVGProps<SVGFEComponentTransferElement>
157
+ feComposite: dom.SVGProps<SVGFECompositeElement>
158
+ feConvolveMatrix: dom.SVGProps<SVGFEConvolveMatrixElement>
159
+ feDiffuseLighting: dom.SVGProps<SVGFEDiffuseLightingElement>
160
+ feDisplacementMap: dom.SVGProps<SVGFEDisplacementMapElement>
161
+ feDistantLight: dom.SVGProps<SVGFEDistantLightElement>
162
+ feDropShadow: dom.SVGProps<SVGFEDropShadowElement>
163
+ feFlood: dom.SVGProps<SVGFEFloodElement>
164
+ feFuncA: dom.SVGProps<SVGFEFuncAElement>
165
+ feFuncB: dom.SVGProps<SVGFEFuncBElement>
166
+ feFuncG: dom.SVGProps<SVGFEFuncGElement>
167
+ feFuncR: dom.SVGProps<SVGFEFuncRElement>
168
+ feGaussianBlur: dom.SVGProps<SVGFEGaussianBlurElement>
169
+ feImage: dom.SVGProps<SVGFEImageElement>
170
+ feMerge: dom.SVGProps<SVGFEMergeElement>
171
+ feMergeNode: dom.SVGProps<SVGFEMergeNodeElement>
172
+ feMorphology: dom.SVGProps<SVGFEMorphologyElement>
173
+ feOffset: dom.SVGProps<SVGFEOffsetElement>
174
+ fePointLight: dom.SVGProps<SVGFEPointLightElement>
175
+ feSpecularLighting: dom.SVGProps<SVGFESpecularLightingElement>
176
+ feSpotLight: dom.SVGProps<SVGFESpotLightElement>
177
+ feTile: dom.SVGProps<SVGFETileElement>
178
+ feTurbulence: dom.SVGProps<SVGFETurbulenceElement>
179
+ filter: dom.SVGProps<SVGFilterElement>
180
+ foreignObject: dom.SVGProps<SVGForeignObjectElement>
181
+ g: dom.SVGProps<SVGGElement>
182
+ image: dom.SVGProps<SVGImageElement>
183
+ line: dom.SVGProps<SVGLineElement>
184
+ linearGradient: dom.SVGProps<SVGLinearGradientElement>
185
+ marker: dom.SVGProps<SVGMarkerElement>
186
+ mask: dom.SVGProps<SVGMaskElement>
187
+ metadata: dom.SVGProps<SVGMetadataElement>
188
+ mpath: dom.SVGProps<SVGMPathElement>
189
+ path: dom.SVGProps<SVGPathElement>
190
+ pattern: dom.SVGProps<SVGPatternElement>
191
+ polygon: dom.SVGProps<SVGPolygonElement>
192
+ polyline: dom.SVGProps<SVGPolylineElement>
193
+ radialGradient: dom.SVGProps<SVGRadialGradientElement>
194
+ rect: dom.SVGProps<SVGRectElement>
195
+ set: dom.SVGProps<SVGSetElement>
196
+ stop: dom.SVGProps<SVGStopElement>
197
+ switch: dom.SVGProps<SVGSwitchElement>
198
+ symbol: dom.SVGProps<SVGSymbolElement>
199
+ text: dom.SVGProps<SVGTextElement>
200
+ textPath: dom.SVGProps<SVGTextPathElement>
201
+ tspan: dom.SVGProps<SVGTSpanElement>
202
+ use: dom.SVGProps<SVGUseElement>
203
+ view: dom.SVGProps<SVGViewElement>
204
+ }
205
+
206
+ export interface IntrinsicMathMLElements {
207
+ annotation: dom.AnnotationMathMLProps<MathMLElement>
208
+ 'annotation-xml': dom.AnnotationXmlMathMLProps<MathMLElement>
209
+ /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/maction */
210
+ maction: dom.MActionMathMLProps<MathMLElement>
211
+ math: dom.MathMathMLProps<MathMLElement>
212
+ /** This feature is non-standard. See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/menclose */
213
+ menclose: dom.MEncloseMathMLProps<MathMLElement>
214
+ merror: dom.MErrorMathMLProps<MathMLElement>
215
+ /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mfenced */
216
+ mfenced: dom.MFencedMathMLProps<MathMLElement>
217
+ mfrac: dom.MFracMathMLProps<MathMLElement>
218
+ mi: dom.MiMathMLProps<MathMLElement>
219
+ mmultiscripts: dom.MmultiScriptsMathMLProps<MathMLElement>
220
+ mn: dom.MNMathMLProps<MathMLElement>
221
+ mo: dom.MOMathMLProps<MathMLElement>
222
+ mover: dom.MOverMathMLProps<MathMLElement>
223
+ mpadded: dom.MPaddedMathMLProps<MathMLElement>
224
+ mphantom: dom.MPhantomMathMLProps<MathMLElement>
225
+ mprescripts: dom.MPrescriptsMathMLProps<MathMLElement>
226
+ mroot: dom.MRootMathMLProps<MathMLElement>
227
+ mrow: dom.MRowMathMLProps<MathMLElement>
228
+ ms: dom.MSMathMLProps<MathMLElement>
229
+ mspace: dom.MSpaceMathMLProps<MathMLElement>
230
+ msqrt: dom.MSqrtMathMLProps<MathMLElement>
231
+ mstyle: dom.MStyleMathMLProps<MathMLElement>
232
+ msub: dom.MSubMathMLProps<MathMLElement>
233
+ msubsup: dom.MSubsupMathMLProps<MathMLElement>
234
+ msup: dom.MSupMathMLProps<MathMLElement>
235
+ mtable: dom.MTableMathMLProps<MathMLElement>
236
+ mtd: dom.MTdMathMLProps<MathMLElement>
237
+ mtext: dom.MTextMathMLProps<MathMLElement>
238
+ mtr: dom.MTrMathMLProps<MathMLElement>
239
+ munder: dom.MUnderMathMLProps<MathMLElement>
240
+ munderover: dom.MUnderMathMLProps<MathMLElement>
241
+ semantics: dom.SemanticsMathMLProps<MathMLElement>
242
+ }
243
+
244
+ export interface IntrinsicHTMLElements {
245
+ a: dom.AccessibleAnchorHTMLProps<HTMLAnchorElement>
246
+ abbr: dom.HTMLProps<HTMLElement>
247
+ address: dom.HTMLProps<HTMLElement>
248
+ area: dom.AccessibleAreaHTMLProps<HTMLAreaElement>
249
+ article: dom.ArticleHTMLProps<HTMLElement>
250
+ aside: dom.AsideHTMLProps<HTMLElement>
251
+ audio: dom.AudioHTMLProps<HTMLAudioElement>
252
+ b: dom.HTMLProps<HTMLElement>
253
+ base: dom.BaseHTMLProps<HTMLBaseElement>
254
+ bdi: dom.HTMLProps<HTMLElement>
255
+ bdo: dom.HTMLProps<HTMLElement>
256
+ big: dom.HTMLProps<HTMLElement>
257
+ blockquote: dom.BlockquoteHTMLProps<HTMLQuoteElement>
258
+ body: dom.HTMLProps<HTMLBodyElement>
259
+ br: dom.BrHTMLProps<HTMLBRElement>
260
+ button: dom.ButtonHTMLProps<HTMLButtonElement>
261
+ canvas: dom.CanvasHTMLProps<HTMLCanvasElement>
262
+ caption: dom.CaptionHTMLProps<HTMLTableCaptionElement>
263
+ cite: dom.HTMLProps<HTMLElement>
264
+ code: dom.HTMLProps<HTMLElement>
265
+ col: dom.ColHTMLProps<HTMLTableColElement>
266
+ colgroup: dom.ColgroupHTMLProps<HTMLTableColElement>
267
+ data: dom.DataHTMLProps<HTMLDataElement>
268
+ datalist: dom.DataListHTMLProps<HTMLDataListElement>
269
+ dd: dom.DdHTMLProps<HTMLElement>
270
+ del: dom.DelHTMLProps<HTMLModElement>
271
+ details: dom.DetailsHTMLProps<HTMLDetailsElement>
272
+ dfn: dom.HTMLProps<HTMLElement>
273
+ dialog: dom.DialogHTMLProps<HTMLDialogElement>
274
+ div: dom.HTMLProps<HTMLDivElement>
275
+ dl: dom.DlHTMLProps<HTMLDListElement>
276
+ dt: dom.DtHTMLProps<HTMLElement>
277
+ em: dom.HTMLProps<HTMLElement>
278
+ embed: dom.EmbedHTMLProps<HTMLEmbedElement>
279
+ fieldset: dom.FieldsetHTMLProps<HTMLFieldSetElement>
280
+ figcaption: dom.FigcaptionHTMLProps<HTMLElement>
281
+ figure: dom.HTMLProps<HTMLElement>
282
+ footer: dom.FooterHTMLProps<HTMLElement>
283
+ form: dom.FormHTMLProps<HTMLFormElement>
284
+ h1: dom.HeadingHTMLProps<HTMLHeadingElement>
285
+ h2: dom.HeadingHTMLProps<HTMLHeadingElement>
286
+ h3: dom.HeadingHTMLProps<HTMLHeadingElement>
287
+ h4: dom.HeadingHTMLProps<HTMLHeadingElement>
288
+ h5: dom.HeadingHTMLProps<HTMLHeadingElement>
289
+ h6: dom.HeadingHTMLProps<HTMLHeadingElement>
290
+ head: dom.HeadHTMLProps<HTMLHeadElement>
291
+ header: dom.HeaderHTMLProps<HTMLElement>
292
+ hgroup: dom.HTMLProps<HTMLElement>
293
+ hr: dom.HrHTMLProps<HTMLHRElement>
294
+ html: dom.HtmlHTMLProps<HTMLHtmlElement>
295
+ i: dom.HTMLProps<HTMLElement>
296
+ iframe: dom.IframeHTMLProps<HTMLIFrameElement>
297
+ img: dom.AccessibleImgHTMLProps<HTMLImageElement>
298
+ input: dom.AccessibleInputHTMLProps<HTMLInputElement>
299
+ ins: dom.InsHTMLProps<HTMLModElement>
300
+ kbd: dom.HTMLProps<HTMLElement>
301
+ keygen: dom.KeygenHTMLProps<HTMLUnknownElement>
302
+ label: dom.LabelHTMLProps<HTMLLabelElement>
303
+ legend: dom.LegendHTMLProps<HTMLLegendElement>
304
+ li: dom.LiHTMLProps<HTMLLIElement>
305
+ link: dom.LinkHTMLProps<HTMLLinkElement>
306
+ main: dom.MainHTMLProps<HTMLElement>
307
+ map: dom.MapHTMLProps<HTMLMapElement>
308
+ mark: dom.HTMLProps<HTMLElement>
309
+ marquee: dom.MarqueeHTMLProps<HTMLMarqueeElement>
310
+ menu: dom.MenuHTMLProps<HTMLMenuElement>
311
+ menuitem: dom.HTMLProps<HTMLUnknownElement>
312
+ meta: dom.MetaHTMLProps<HTMLMetaElement>
313
+ meter: dom.MeterHTMLProps<HTMLMeterElement>
314
+ nav: dom.NavHTMLProps<HTMLElement>
315
+ noscript: dom.NoScriptHTMLProps<HTMLElement>
316
+ object: dom.ObjectHTMLProps<HTMLObjectElement>
317
+ ol: dom.OlHTMLProps<HTMLOListElement>
318
+ optgroup: dom.OptgroupHTMLProps<HTMLOptGroupElement>
319
+ option: dom.OptionHTMLProps<HTMLOptionElement>
320
+ output: dom.OutputHTMLProps<HTMLOutputElement>
321
+ p: dom.HTMLProps<HTMLParagraphElement>
322
+ param: dom.ParamHTMLProps<HTMLParamElement>
323
+ picture: dom.PictureHTMLProps<HTMLPictureElement>
324
+ pre: dom.HTMLProps<HTMLPreElement>
325
+ progress: dom.ProgressHTMLProps<HTMLProgressElement>
326
+ q: dom.QuoteHTMLProps<HTMLQuoteElement>
327
+ rp: dom.HTMLProps<HTMLElement>
328
+ rt: dom.HTMLProps<HTMLElement>
329
+ ruby: dom.HTMLProps<HTMLElement>
330
+ s: dom.HTMLProps<HTMLElement>
331
+ samp: dom.HTMLProps<HTMLElement>
332
+ script: dom.ScriptHTMLProps<HTMLScriptElement>
333
+ search: dom.SearchHTMLProps<HTMLElement>
334
+ section: dom.HTMLProps<HTMLElement>
335
+ select: dom.AccessibleSelectHTMLProps<HTMLSelectElement>
336
+ slot: dom.SlotHTMLProps<HTMLSlotElement>
337
+ small: dom.HTMLProps<HTMLElement>
338
+ source: dom.SourceHTMLProps<HTMLSourceElement>
339
+ span: dom.HTMLProps<HTMLSpanElement>
340
+ strong: dom.HTMLProps<HTMLElement>
341
+ style: dom.StyleHTMLProps<HTMLStyleElement>
342
+ sub: dom.HTMLProps<HTMLElement>
343
+ summary: dom.HTMLProps<HTMLElement>
344
+ sup: dom.HTMLProps<HTMLElement>
345
+ table: dom.TableHTMLProps<HTMLTableElement>
346
+ tbody: dom.HTMLProps<HTMLTableSectionElement>
347
+ td: dom.TdHTMLProps<HTMLTableCellElement>
348
+ template: dom.TemplateHTMLProps<HTMLTemplateElement>
349
+ textarea: dom.TextareaHTMLProps<HTMLTextAreaElement>
350
+ tfoot: dom.HTMLProps<HTMLTableSectionElement>
351
+ th: dom.ThHTMLProps<HTMLTableCellElement>
352
+ thead: dom.HTMLProps<HTMLTableSectionElement>
353
+ time: dom.TimeHTMLProps<HTMLTimeElement>
354
+ title: dom.TitleHTMLProps<HTMLTitleElement>
355
+ tr: dom.HTMLProps<HTMLTableRowElement>
356
+ track: dom.TrackHTMLProps<HTMLTrackElement>
357
+ u: dom.UlHTMLProps<HTMLElement>
358
+ ul: dom.HTMLProps<HTMLUListElement>
359
+ var: dom.HTMLProps<HTMLElement>
360
+ video: dom.VideoHTMLProps<HTMLVideoElement>
361
+ wbr: dom.WbrHTMLProps<HTMLElement>
362
+ }
363
+
364
+ export interface IntrinsicElements
365
+ extends IntrinsicSVGElements,
366
+ IntrinsicMathMLElements,
367
+ IntrinsicHTMLElements {}
368
+ }
369
+ }
370
+
371
+ function normalizeElementProps(props: ElementProps | null | undefined): ElementProps {
372
+ if (!props) return {}
373
+ if (!('mix' in props)) return props
374
+
375
+ let { mix, ...rest } = props
376
+ let normalizedMix = normalizeMixValue(mix)
377
+ return normalizedMix === undefined ? rest : { ...rest, mix: normalizedMix }
378
+ }
379
+
380
+ function normalizeMixValue(mix: unknown): unknown[] | undefined {
381
+ if (!mix) return undefined
382
+
383
+ let normalizedMix = flattenMixValue(mix)
384
+ return normalizedMix.length === 0 ? undefined : normalizedMix
385
+ }
386
+
387
+ function flattenMixValue(mix: unknown): unknown[] {
388
+ if (!mix) return []
389
+ if (!Array.isArray(mix)) return [mix]
390
+
391
+ let flattened: unknown[] = []
392
+
393
+ for (let item of mix) {
394
+ flattened.push(...flattenMixValue(item))
395
+ }
396
+
397
+ return flattened
398
+ }
@@ -0,0 +1,35 @@
1
+ import { createMixin } from './mixin.ts'
2
+ import type { ElementProps } from '../jsx.ts'
3
+ import type { MixinDescriptor } from './mixin.ts'
4
+ import { createElement } from '../create-element.ts'
5
+
6
+ const attrsMixin = createMixin<Element, [defaults: ElementProps], ElementProps>(
7
+ (handle) => (defaults, props) => {
8
+ let nextProps = props
9
+
10
+ for (let key in defaults) {
11
+ if (props[key] !== undefined) continue
12
+ if (nextProps === props) nextProps = { ...props }
13
+ nextProps[key] = defaults[key]
14
+ }
15
+
16
+ return nextProps === props ? handle.element : createElement(handle.element, nextProps)
17
+ },
18
+ )
19
+
20
+ /**
21
+ * Applies default host props unless the element already provides them explicitly.
22
+ *
23
+ * @param defaults Default props to apply when the element does not already define them.
24
+ * @returns A mixin descriptor that provides default host props.
25
+ */
26
+ export function attrs<
27
+ node extends EventTarget = Element,
28
+ defaults extends ElementProps = ElementProps,
29
+ >(defaults: Partial<defaults>): MixinDescriptor<node, [Partial<ElementProps>], ElementProps> {
30
+ return attrsMixin(defaults as ElementProps) as unknown as MixinDescriptor<
31
+ node,
32
+ [Partial<ElementProps>],
33
+ ElementProps
34
+ >
35
+ }
@@ -0,0 +1,131 @@
1
+ import { createMixin, renderMixinElement } from './mixin.ts'
2
+ import { navigate } from '../navigation.ts'
3
+ import { on } from './on-mixin.ts'
4
+ import type { ElementProps } from '../jsx.ts'
5
+
6
+ import type { NavigationOptions } from '../navigation.ts'
7
+
8
+ type LinkCurrentProps = ElementProps & {
9
+ disabled?: boolean
10
+ role?: string
11
+ tabIndex?: number
12
+ tabindex?: number
13
+ type?: string
14
+ contentEditable?: boolean | string
15
+ contenteditable?: boolean | string
16
+ 'aria-disabled'?: boolean | 'true' | 'false'
17
+ }
18
+
19
+ const nativeLinkHostTypes = new Set(['a', 'area'])
20
+
21
+ /**
22
+ * Adds client-side navigation behavior to anchor-like elements.
23
+ */
24
+ export const link = createMixin<
25
+ HTMLElement,
26
+ [href: string, options?: NavigationOptions],
27
+ LinkCurrentProps
28
+ >((handle, hostType) => {
29
+ let suppressKeyboardClick = false
30
+
31
+ return (href, options, props: LinkCurrentProps) => {
32
+ if (nativeLinkHostTypes.has(hostType)) {
33
+ return renderMixinElement(handle.element, {
34
+ ...(props ?? {}),
35
+ href,
36
+ ...(options?.target == null ? {} : { 'rmx-target': options.target }),
37
+ ...(options?.src == null ? {} : { 'rmx-src': options.src }),
38
+ ...(options?.resetScroll === false ? { 'rmx-reset-scroll': 'false' } : {}),
39
+ })
40
+ }
41
+
42
+ let nextProps = { ...props }
43
+ if (nextProps.role == null) {
44
+ nextProps.role = 'link'
45
+ }
46
+ if (nextProps.disabled === true && nextProps['aria-disabled'] == null) {
47
+ nextProps['aria-disabled'] = 'true'
48
+ }
49
+ if (hostType === 'button' && nextProps.type == null) {
50
+ nextProps.type = 'button'
51
+ }
52
+ if (
53
+ hostType !== 'button' &&
54
+ nextProps.tabIndex == null &&
55
+ nextProps.tabindex == null &&
56
+ nextProps.contentEditable == null &&
57
+ nextProps.contenteditable == null
58
+ ) {
59
+ nextProps.tabIndex = 0
60
+ }
61
+
62
+ return renderMixinElement(handle.element, {
63
+ ...nextProps,
64
+ mix: [
65
+ on('click', (event) => {
66
+ if (event.detail === 0 && suppressKeyboardClick) {
67
+ suppressKeyboardClick = false
68
+ event.preventDefault()
69
+ return
70
+ }
71
+
72
+ suppressKeyboardClick = false
73
+ if (isDisabledElement(event.currentTarget)) {
74
+ event.preventDefault()
75
+ return
76
+ }
77
+ if (event.button !== 0) return
78
+
79
+ event.preventDefault()
80
+ if (event.metaKey || event.ctrlKey) {
81
+ globalThis.open(href, '_blank')
82
+ return
83
+ }
84
+
85
+ void navigate(href, options)
86
+ }),
87
+ on('auxclick', (event) => {
88
+ suppressKeyboardClick = false
89
+ if (isDisabledElement(event.currentTarget)) {
90
+ event.preventDefault()
91
+ return
92
+ }
93
+ if (event.button !== 1) return
94
+
95
+ event.preventDefault()
96
+ globalThis.open(href, '_blank')
97
+ }),
98
+ on('keydown', (event) => {
99
+ if (event.key === 'Enter') {
100
+ if (event.repeat) return
101
+ if (isDisabledElement(event.currentTarget)) {
102
+ event.preventDefault()
103
+ return
104
+ }
105
+
106
+ suppressKeyboardClick = hostType === 'button'
107
+ event.preventDefault()
108
+ void navigate(href, options)
109
+ return
110
+ }
111
+
112
+ if (hostType === 'button' && event.key === ' ') {
113
+ suppressKeyboardClick = true
114
+ event.preventDefault()
115
+ }
116
+ }),
117
+ on('keyup', (event) => {
118
+ if (hostType === 'button' && event.key === ' ') {
119
+ event.preventDefault()
120
+ }
121
+ }),
122
+ ],
123
+ })
124
+ }
125
+ })
126
+
127
+ function isDisabledElement(node: Element) {
128
+ return (
129
+ ('disabled' in node && node.disabled === true) || node.getAttribute('aria-disabled') === 'true'
130
+ )
131
+ }