@askrjs/askr 0.0.7 → 0.0.9

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.
@@ -1,6 +1,9 @@
1
1
  // src/foundations/structures/layout.tsx
2
2
  function layout(Layout) {
3
- return (children, props) => Layout({ ...props, children });
3
+ return (children, props) => {
4
+ const mergedProps = { ...props, children };
5
+ return Layout(mergedProps);
6
+ };
4
7
  }
5
8
 
6
9
  // src/common/jsx.ts
@@ -95,24 +98,117 @@ var DefaultPortal = (() => {
95
98
  return Host;
96
99
  })();
97
100
 
98
- // src/foundations/utilities/composeHandlers.ts
101
+ // src/foundations/structures/collection.ts
102
+ function createCollection() {
103
+ const registry = /* @__PURE__ */ new Map();
104
+ function register(node, metadata) {
105
+ const item = { node, metadata };
106
+ registry.set(node, item);
107
+ return () => {
108
+ registry.delete(node);
109
+ };
110
+ }
111
+ function items() {
112
+ return Array.from(registry.values());
113
+ }
114
+ function clear() {
115
+ registry.clear();
116
+ }
117
+ function size() {
118
+ return registry.size;
119
+ }
120
+ return {
121
+ register,
122
+ items,
123
+ clear,
124
+ size
125
+ };
126
+ }
127
+
128
+ // src/foundations/structures/layer.ts
129
+ function createLayer() {
130
+ const stack = [];
131
+ let nextId = 1;
132
+ function register(options) {
133
+ const id = nextId++;
134
+ const entry = { id, options };
135
+ stack.push(entry);
136
+ function isTop() {
137
+ return stack[stack.length - 1]?.id === id;
138
+ }
139
+ function unregister() {
140
+ const index = stack.findIndex((e) => e.id === id);
141
+ if (index !== -1) {
142
+ stack.splice(index, 1);
143
+ }
144
+ }
145
+ return {
146
+ id,
147
+ isTop,
148
+ unregister
149
+ };
150
+ }
151
+ function layers() {
152
+ return stack.map((entry) => ({
153
+ id: entry.id,
154
+ isTop: () => stack[stack.length - 1]?.id === entry.id,
155
+ unregister: () => {
156
+ const index = stack.findIndex((e) => e.id === entry.id);
157
+ if (index !== -1) {
158
+ stack.splice(index, 1);
159
+ }
160
+ }
161
+ }));
162
+ }
163
+ function handleEscape() {
164
+ const top = stack[stack.length - 1];
165
+ if (top) {
166
+ top.options.onEscape?.();
167
+ }
168
+ }
169
+ function handleOutsidePointer(e) {
170
+ const top = stack[stack.length - 1];
171
+ if (!top) return;
172
+ const node = top.options.node;
173
+ if (node && e.target instanceof Node) {
174
+ if (!node.contains(e.target)) {
175
+ top.options.onOutsidePointer?.(e);
176
+ }
177
+ } else {
178
+ top.options.onOutsidePointer?.(e);
179
+ }
180
+ }
181
+ return {
182
+ register,
183
+ layers,
184
+ handleEscape,
185
+ handleOutsidePointer
186
+ };
187
+ }
188
+
189
+ // src/foundations/utilities/compose-handlers.ts
99
190
  function isDefaultPrevented(value) {
100
191
  return typeof value === "object" && value !== null && "defaultPrevented" in value && value.defaultPrevented === true;
101
192
  }
102
193
  function composeHandlers(first, second, options) {
194
+ if (!first && !second) {
195
+ return noop;
196
+ }
197
+ if (!first) return second;
198
+ if (!second) return first;
103
199
  const checkDefaultPrevented = options?.checkDefaultPrevented !== false;
104
200
  return function composed(...args) {
105
- if (typeof first === "function") first(...args);
106
- if (checkDefaultPrevented) {
107
- if (isDefaultPrevented(args[0])) {
108
- return;
109
- }
201
+ first(...args);
202
+ if (checkDefaultPrevented && isDefaultPrevented(args[0])) {
203
+ return;
110
204
  }
111
- if (typeof second === "function") second(...args);
205
+ second(...args);
112
206
  };
113
207
  }
208
+ function noop() {
209
+ }
114
210
 
115
- // src/foundations/utilities/mergeProps.ts
211
+ // src/foundations/utilities/merge-props.ts
116
212
  function isEventHandlerKey(key) {
117
213
  return key.startsWith("on");
118
214
  }
@@ -148,7 +244,7 @@ function ariaSelected(selected) {
148
244
  return selected === void 0 ? {} : { "aria-selected": String(selected) };
149
245
  }
150
246
 
151
- // src/foundations/utilities/composeRef.ts
247
+ // src/foundations/utilities/compose-ref.ts
152
248
  function setRef(ref, value) {
153
249
  if (!ref) return;
154
250
  if (typeof ref === "function") {
@@ -166,7 +262,7 @@ function composeRefs(...refs) {
166
262
  };
167
263
  }
168
264
 
169
- // src/foundations/utilities/useId.ts
265
+ // src/foundations/utilities/use-id.ts
170
266
  function useId(options) {
171
267
  const prefix = options.prefix ?? "askr";
172
268
  return `${prefix}-${String(options.id)}`;
@@ -982,7 +1078,11 @@ function pressable({
982
1078
  props.role = "button";
983
1079
  props.tabIndex = disabled ? -1 : 0;
984
1080
  props.onKeyDown = (e) => {
985
- if (disabled) return;
1081
+ if (disabled) {
1082
+ e.preventDefault?.();
1083
+ e.stopPropagation?.();
1084
+ return;
1085
+ }
986
1086
  if (e.key === "Enter") {
987
1087
  e.preventDefault?.();
988
1088
  onPress?.(e);
@@ -993,7 +1093,11 @@ function pressable({
993
1093
  }
994
1094
  };
995
1095
  props.onKeyUp = (e) => {
996
- if (disabled) return;
1096
+ if (disabled) {
1097
+ e.preventDefault?.();
1098
+ e.stopPropagation?.();
1099
+ return;
1100
+ }
997
1101
  if (e.key === " ") {
998
1102
  e.preventDefault?.();
999
1103
  onPress?.(e);
@@ -1004,18 +1108,32 @@ function pressable({
1004
1108
  }
1005
1109
 
1006
1110
  // src/foundations/interactions/dismissable.ts
1007
- function dismissable({ onDismiss, disabled }) {
1008
- return {
1009
- // Prop for the component root to handle Escape
1010
- onKeyDown: disabled ? void 0 : (e) => {
1011
- if (e.key === "Escape") {
1012
- onDismiss?.();
1013
- }
1014
- },
1015
- // Factory: runtime should attach this listener at the appropriate scope.
1016
- outsideListener: disabled ? void 0 : (isInside) => (e) => {
1017
- if (!isInside(e.target)) onDismiss?.();
1111
+ function dismissable({
1112
+ node,
1113
+ disabled,
1114
+ onDismiss
1115
+ }) {
1116
+ function handleKeyDown(e) {
1117
+ if (disabled) return;
1118
+ if (e.key === "Escape") {
1119
+ e.preventDefault?.();
1120
+ e.stopPropagation?.();
1121
+ onDismiss?.("escape");
1018
1122
  }
1123
+ }
1124
+ function handlePointerDownCapture(e) {
1125
+ if (disabled) return;
1126
+ const target = e.target;
1127
+ if (!(target instanceof Node)) return;
1128
+ if (!node) return;
1129
+ if (!node.contains(target)) {
1130
+ onDismiss?.("outside");
1131
+ }
1132
+ }
1133
+ return {
1134
+ onKeyDown: handleKeyDown,
1135
+ // Use capture phase to catch events before they bubble
1136
+ onPointerDownCapture: handlePointerDownCapture
1019
1137
  };
1020
1138
  }
1021
1139
 
@@ -1046,6 +1164,111 @@ function hoverable({
1046
1164
  };
1047
1165
  }
1048
1166
 
1049
- export { DefaultPortal, Presence, Slot, ariaDisabled, ariaExpanded, ariaSelected, composeHandlers, composeRefs, controllableState, definePortal, dismissable, focusable, hoverable, isControlled, layout, makeControllable, mergeProps, pressable, resolveControllable, setRef, useId };
1167
+ // src/foundations/interactions/roving-focus.ts
1168
+ function rovingFocus(options) {
1169
+ const {
1170
+ currentIndex,
1171
+ itemCount,
1172
+ orientation = "horizontal",
1173
+ loop = false,
1174
+ onNavigate,
1175
+ isDisabled
1176
+ } = options;
1177
+ function findNextIndex(from, direction) {
1178
+ let next = from + direction;
1179
+ if (loop) {
1180
+ if (next < 0) next = itemCount - 1;
1181
+ if (next >= itemCount) next = 0;
1182
+ } else {
1183
+ if (next < 0 || next >= itemCount) return void 0;
1184
+ }
1185
+ if (isDisabled?.(next)) {
1186
+ if (next === from) return void 0;
1187
+ return findNextIndex(next, direction);
1188
+ }
1189
+ return next;
1190
+ }
1191
+ function handleKeyDown(e) {
1192
+ const { key } = e;
1193
+ let direction;
1194
+ if (orientation === "horizontal" || orientation === "both") {
1195
+ if (key === "ArrowRight") direction = 1;
1196
+ if (key === "ArrowLeft") direction = -1;
1197
+ }
1198
+ if (orientation === "vertical" || orientation === "both") {
1199
+ if (key === "ArrowDown") direction = 1;
1200
+ if (key === "ArrowUp") direction = -1;
1201
+ }
1202
+ if (direction === void 0) return;
1203
+ const nextIndex = findNextIndex(currentIndex, direction);
1204
+ if (nextIndex === void 0) return;
1205
+ e.preventDefault?.();
1206
+ e.stopPropagation?.();
1207
+ onNavigate?.(nextIndex);
1208
+ }
1209
+ return {
1210
+ container: {
1211
+ onKeyDown: handleKeyDown
1212
+ },
1213
+ item: (index) => ({
1214
+ tabIndex: index === currentIndex ? 0 : -1,
1215
+ "data-roving-index": index
1216
+ })
1217
+ };
1218
+ }
1219
+
1220
+ // src/foundations/interactions/interaction-policy.ts
1221
+ function applyInteractionPolicy({
1222
+ isNative,
1223
+ disabled,
1224
+ onPress,
1225
+ ref
1226
+ }) {
1227
+ function invokePress(e) {
1228
+ if (disabled) {
1229
+ e.preventDefault?.();
1230
+ return;
1231
+ }
1232
+ onPress?.(e);
1233
+ }
1234
+ if (isNative) {
1235
+ return {
1236
+ disabled: disabled || void 0,
1237
+ onClick: (e) => invokePress(e),
1238
+ ref
1239
+ };
1240
+ }
1241
+ const interaction = pressable({
1242
+ disabled,
1243
+ isNativeButton: false,
1244
+ onPress: (e) => invokePress(e)
1245
+ });
1246
+ return {
1247
+ ...interaction,
1248
+ "aria-disabled": disabled || void 0,
1249
+ tabIndex: disabled ? -1 : interaction.tabIndex ?? 0,
1250
+ ref
1251
+ };
1252
+ }
1253
+ function mergeInteractionProps(childProps, policyProps, userProps) {
1254
+ let out = mergeProps(childProps, policyProps);
1255
+ if (userProps) out = mergeProps(out, userProps);
1256
+ for (const k in out) {
1257
+ if (!k.startsWith("on")) continue;
1258
+ const policyHandler = policyProps?.[k];
1259
+ const userHandler = userProps?.[k];
1260
+ const childHandler = childProps?.[k];
1261
+ if (policyHandler || userHandler || childHandler) {
1262
+ out[k] = composeHandlers(
1263
+ policyHandler,
1264
+ composeHandlers(userHandler, childHandler)
1265
+ );
1266
+ }
1267
+ }
1268
+ out.ref = composeRefs(childProps?.ref, userProps?.ref, policyProps?.ref);
1269
+ return out;
1270
+ }
1271
+
1272
+ export { DefaultPortal, Presence, Slot, applyInteractionPolicy, ariaDisabled, ariaExpanded, ariaSelected, composeHandlers, composeRefs, controllableState, createCollection, createLayer, definePortal, dismissable, focusable, hoverable, isControlled, layout, makeControllable, mergeInteractionProps, mergeProps, pressable, resolveControllable, rovingFocus, setRef, useId };
1050
1273
  //# sourceMappingURL=index.js.map
1051
1274
  //# sourceMappingURL=index.js.map