@arun-dev/headless 0.2.1 → 0.3.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.
@@ -75,6 +75,7 @@ function booleanAttribute(whenTrue, whenFalse) {
75
75
  return whenFalse ? { [whenFalse]: "" } : null;
76
76
  };
77
77
  }
78
+ var disabledAttribute = booleanAttribute("data-disabled");
78
79
 
79
80
  // src/core/useRender.ts
80
81
  import { cloneElement, createElement, isValidElement } from "react";
@@ -131,6 +132,7 @@ export {
131
132
  mergeProps,
132
133
  getStateAttributes,
133
134
  booleanAttribute,
135
+ disabledAttribute,
134
136
  useRender,
135
137
  useControlled
136
138
  };
package/dist/index.cjs CHANGED
@@ -21,8 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  booleanAttribute: () => booleanAttribute,
24
+ disabledAttribute: () => disabledAttribute,
24
25
  getStateAttributes: () => getStateAttributes,
25
26
  mergeProps: () => mergeProps,
27
+ retractActivationProps: () => retractActivationProps,
28
+ useButton: () => useButton,
26
29
  useControlled: () => useControlled,
27
30
  useRender: () => useRender
28
31
  });
@@ -102,6 +105,7 @@ function booleanAttribute(whenTrue, whenFalse) {
102
105
  return whenFalse ? { [whenFalse]: "" } : null;
103
106
  };
104
107
  }
108
+ var disabledAttribute = booleanAttribute("data-disabled");
105
109
 
106
110
  // src/core/useRender.ts
107
111
  function useRender({
@@ -151,11 +155,52 @@ function useControlled({
151
155
  );
152
156
  return [value, setValue];
153
157
  }
158
+
159
+ // src/useButton.ts
160
+ var ACTIVATION_HANDLERS = [
161
+ "onClick",
162
+ "onDoubleClick",
163
+ "onMouseDown",
164
+ "onMouseUp",
165
+ "onPointerDown",
166
+ "onPointerUp",
167
+ "onTouchStart",
168
+ "onTouchEnd",
169
+ "onKeyDown",
170
+ "onKeyUp",
171
+ "onKeyPress"
172
+ ];
173
+ function useButton({ disabled = false, native, props = {} }) {
174
+ if (!disabled) return props;
175
+ if (native) return { ...props, disabled: true, "data-disabled": "" };
176
+ const sanitised = {};
177
+ for (const key of Object.keys(props)) {
178
+ if (key === "href" || ACTIVATION_HANDLERS.includes(key)) continue;
179
+ sanitised[key] = props[key];
180
+ }
181
+ return {
182
+ ...sanitised,
183
+ "aria-disabled": true,
184
+ "data-disabled": "",
185
+ // Mirrors a native disabled button, which is not focusable.
186
+ tabIndex: -1
187
+ };
188
+ }
189
+ function retractActivationProps(props) {
190
+ const overrides = {};
191
+ for (const key of Object.keys(props)) {
192
+ if (key === "href" || ACTIVATION_HANDLERS.includes(key)) overrides[key] = void 0;
193
+ }
194
+ return overrides;
195
+ }
154
196
  // Annotate the CommonJS export names for ESM import in node:
155
197
  0 && (module.exports = {
156
198
  booleanAttribute,
199
+ disabledAttribute,
157
200
  getStateAttributes,
158
201
  mergeProps,
202
+ retractActivationProps,
203
+ useButton,
159
204
  useControlled,
160
205
  useRender
161
206
  });
package/dist/index.d.cts CHANGED
@@ -51,6 +51,12 @@ declare function getStateAttributes<State extends Record<string, unknown>>(state
51
51
  * checked: booleanAttribute('data-checked', 'data-unchecked')
52
52
  */
53
53
  declare function booleanAttribute(whenTrue: string, whenFalse?: string): (value: unknown) => Record<string, string> | null;
54
+ /**
55
+ * The shared spelling of the disabled state. Every component uses this rather than
56
+ * writing the string again, so `[data-disabled]` means the same thing system-wide and
57
+ * a typo cannot silently split the CSS contract.
58
+ */
59
+ declare const disabledAttribute: (value: unknown) => Record<string, string> | null;
54
60
 
55
61
  /**
56
62
  * Resolves what a component part actually renders.
@@ -96,4 +102,26 @@ declare function useControlled<T>({ controlled, default: defaultValue, name, sta
96
102
  state?: string;
97
103
  }): [T, (next: T) => void];
98
104
 
99
- export { type StateAttributeMapping, type UnknownProps, type UseRenderParams, booleanAttribute, getStateAttributes, mergeProps, useControlled, useRender };
105
+ interface UseButtonParams {
106
+ disabled?: boolean;
107
+ /** Whether the rendered element is a native `<button>`, which the platform disables for us. */
108
+ native: boolean;
109
+ /** Props destined for the element. Returned unchanged unless `disabled`. */
110
+ props?: UnknownProps;
111
+ }
112
+ declare function useButton({ disabled, native, props }: UseButtonParams): UnknownProps;
113
+ /**
114
+ * Overrides that neutralise a consumer-supplied `render` element.
115
+ *
116
+ * `useButton` sanitises the props a component passes, but a `render` element's own
117
+ * props merge at the highest precedence inside `useRender`, so a `href` written
118
+ * directly on it survives. Those have to be retracted on the element itself:
119
+ *
120
+ * cloneElement(render, retractActivationProps(render.props))
121
+ *
122
+ * `cloneElement` overwrites with `undefined`, which `mergeProps` cannot do — it skips
123
+ * `undefined` so an absent prop never clobbers a present one.
124
+ */
125
+ declare function retractActivationProps(props: UnknownProps): UnknownProps;
126
+
127
+ export { type StateAttributeMapping, type UnknownProps, type UseButtonParams, type UseRenderParams, booleanAttribute, disabledAttribute, getStateAttributes, mergeProps, retractActivationProps, useButton, useControlled, useRender };
package/dist/index.d.ts CHANGED
@@ -51,6 +51,12 @@ declare function getStateAttributes<State extends Record<string, unknown>>(state
51
51
  * checked: booleanAttribute('data-checked', 'data-unchecked')
52
52
  */
53
53
  declare function booleanAttribute(whenTrue: string, whenFalse?: string): (value: unknown) => Record<string, string> | null;
54
+ /**
55
+ * The shared spelling of the disabled state. Every component uses this rather than
56
+ * writing the string again, so `[data-disabled]` means the same thing system-wide and
57
+ * a typo cannot silently split the CSS contract.
58
+ */
59
+ declare const disabledAttribute: (value: unknown) => Record<string, string> | null;
54
60
 
55
61
  /**
56
62
  * Resolves what a component part actually renders.
@@ -96,4 +102,26 @@ declare function useControlled<T>({ controlled, default: defaultValue, name, sta
96
102
  state?: string;
97
103
  }): [T, (next: T) => void];
98
104
 
99
- export { type StateAttributeMapping, type UnknownProps, type UseRenderParams, booleanAttribute, getStateAttributes, mergeProps, useControlled, useRender };
105
+ interface UseButtonParams {
106
+ disabled?: boolean;
107
+ /** Whether the rendered element is a native `<button>`, which the platform disables for us. */
108
+ native: boolean;
109
+ /** Props destined for the element. Returned unchanged unless `disabled`. */
110
+ props?: UnknownProps;
111
+ }
112
+ declare function useButton({ disabled, native, props }: UseButtonParams): UnknownProps;
113
+ /**
114
+ * Overrides that neutralise a consumer-supplied `render` element.
115
+ *
116
+ * `useButton` sanitises the props a component passes, but a `render` element's own
117
+ * props merge at the highest precedence inside `useRender`, so a `href` written
118
+ * directly on it survives. Those have to be retracted on the element itself:
119
+ *
120
+ * cloneElement(render, retractActivationProps(render.props))
121
+ *
122
+ * `cloneElement` overwrites with `undefined`, which `mergeProps` cannot do — it skips
123
+ * `undefined` so an absent prop never clobbers a present one.
124
+ */
125
+ declare function retractActivationProps(props: UnknownProps): UnknownProps;
126
+
127
+ export { type StateAttributeMapping, type UnknownProps, type UseButtonParams, type UseRenderParams, booleanAttribute, disabledAttribute, getStateAttributes, mergeProps, retractActivationProps, useButton, useControlled, useRender };
package/dist/index.js CHANGED
@@ -1,14 +1,56 @@
1
1
  import {
2
2
  booleanAttribute,
3
+ disabledAttribute,
3
4
  getStateAttributes,
4
5
  mergeProps,
5
6
  useControlled,
6
7
  useRender
7
- } from "./chunk-DAO4JK6U.js";
8
+ } from "./chunk-LU4ZQE3V.js";
9
+
10
+ // src/useButton.ts
11
+ var ACTIVATION_HANDLERS = [
12
+ "onClick",
13
+ "onDoubleClick",
14
+ "onMouseDown",
15
+ "onMouseUp",
16
+ "onPointerDown",
17
+ "onPointerUp",
18
+ "onTouchStart",
19
+ "onTouchEnd",
20
+ "onKeyDown",
21
+ "onKeyUp",
22
+ "onKeyPress"
23
+ ];
24
+ function useButton({ disabled = false, native, props = {} }) {
25
+ if (!disabled) return props;
26
+ if (native) return { ...props, disabled: true, "data-disabled": "" };
27
+ const sanitised = {};
28
+ for (const key of Object.keys(props)) {
29
+ if (key === "href" || ACTIVATION_HANDLERS.includes(key)) continue;
30
+ sanitised[key] = props[key];
31
+ }
32
+ return {
33
+ ...sanitised,
34
+ "aria-disabled": true,
35
+ "data-disabled": "",
36
+ // Mirrors a native disabled button, which is not focusable.
37
+ tabIndex: -1
38
+ };
39
+ }
40
+ function retractActivationProps(props) {
41
+ const overrides = {};
42
+ for (const key of Object.keys(props)) {
43
+ if (key === "href" || ACTIVATION_HANDLERS.includes(key)) overrides[key] = void 0;
44
+ }
45
+ return overrides;
46
+ }
8
47
  export {
9
48
  booleanAttribute,
49
+ disabledAttribute,
10
50
  getStateAttributes,
11
51
  mergeProps,
52
+ retractActivationProps,
53
+ useButton,
12
54
  useControlled,
13
55
  useRender
14
56
  };
@@ -141,6 +141,7 @@ function booleanAttribute(whenTrue, whenFalse) {
141
141
  return whenFalse ? { [whenFalse]: "" } : null;
142
142
  };
143
143
  }
144
+ var disabledAttribute = booleanAttribute("data-disabled");
144
145
 
145
146
  // src/core/useRender.ts
146
147
  function useRender({
@@ -172,7 +173,7 @@ function useSwitchRootContext() {
172
173
  // src/switch/stateAttributes.ts
173
174
  var switchStateAttributes = {
174
175
  checked: booleanAttribute("data-checked", "data-unchecked"),
175
- disabled: booleanAttribute("data-disabled")
176
+ disabled: disabledAttribute
176
177
  };
177
178
 
178
179
  // src/switch/root/SwitchRoot.tsx
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  __export,
3
3
  booleanAttribute,
4
+ disabledAttribute,
4
5
  useControlled,
5
6
  useRender
6
- } from "../chunk-DAO4JK6U.js";
7
+ } from "../chunk-LU4ZQE3V.js";
7
8
 
8
9
  // src/switch/index.parts.ts
9
10
  var index_parts_exports = {};
@@ -29,7 +30,7 @@ function useSwitchRootContext() {
29
30
  // src/switch/stateAttributes.ts
30
31
  var switchStateAttributes = {
31
32
  checked: booleanAttribute("data-checked", "data-unchecked"),
32
- disabled: booleanAttribute("data-disabled")
33
+ disabled: disabledAttribute
33
34
  };
34
35
 
35
36
  // src/switch/root/SwitchRoot.tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arun-dev/headless",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Unstyled React behaviour primitives — render engine, controlled/uncontrolled state, and data-* state projection. Ships no CSS and no class names.",
5
5
  "license": "MIT",
6
6
  "type": "module",