@bccampus/ui-components 0.5.3 → 0.5.5

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.
Binary file
@@ -0,0 +1,2 @@
1
+ import { BaseCompositeProps } from './types';
2
+ export declare function LayoutGrid<T extends object>({ data, ...props }: BaseCompositeProps<T>): import("react").JSX.Element;
@@ -0,0 +1,59 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { CompositeComponent } from "./composite-component.js";
3
+ import { useRef, useCallback } from "react";
4
+ import "nanostores";
5
+ import { useKeyboardEvent } from "../../../hooks/use-keyboard-event.js";
6
+ function LayoutGrid({ data, ...props }) {
7
+ const compositeRef = useRef(null);
8
+ const focusElement = useCallback(() => {
9
+ const itemKey = data.focusProvider.focusedItem.get()?.key;
10
+ if (itemKey && compositeRef.current) {
11
+ const focusedItemEl = compositeRef.current.querySelector(`[data-key="${itemKey}"]`);
12
+ if (focusedItemEl) focusedItemEl.focus();
13
+ }
14
+ }, [data]);
15
+ const handleKeyboardEvent = useKeyboardEvent({
16
+ ArrowUp: () => {
17
+ data.focusProvider.focusUp();
18
+ focusElement();
19
+ },
20
+ ArrowDown: () => {
21
+ data.focusProvider.focusDown();
22
+ focusElement();
23
+ },
24
+ Home: () => {
25
+ data.focusProvider.focusToFirst();
26
+ focusElement();
27
+ },
28
+ End: () => {
29
+ data.focusProvider.focusToLast();
30
+ focusElement();
31
+ },
32
+ Space: () => {
33
+ data.selectionProvider?.toggleSelect();
34
+ focusElement();
35
+ }
36
+ });
37
+ const handleItemMouseEvent = useCallback(
38
+ (item) => {
39
+ data.focusProvider.focus(item.key);
40
+ data.selectionProvider?.toggleSelect(item);
41
+ focusElement();
42
+ },
43
+ [data.focusProvider, data.selectionProvider, focusElement]
44
+ );
45
+ return /* @__PURE__ */ jsx(
46
+ CompositeComponent,
47
+ {
48
+ ref: compositeRef,
49
+ variant: "listbox",
50
+ data,
51
+ onKeyDown: handleKeyboardEvent,
52
+ itemMouseEventHandler: handleItemMouseEvent,
53
+ ...props
54
+ }
55
+ );
56
+ }
57
+ export {
58
+ LayoutGrid
59
+ };
@@ -71,7 +71,12 @@ const TileTemplates = {
71
71
  `tile-${tileX}-${tileY}`
72
72
  );
73
73
  },
74
- [TileShape.RandBasic]: (tileX, tileY, tileSize, tileConfig) => TileTemplates[TileShape.Square + Math.floor(Math.random() * 4)](tileX, tileY, tileSize, tileConfig),
74
+ [TileShape.RandBasic]: (tileX, tileY, tileSize, tileConfig) => TileTemplates[TileShape.Square + Math.floor(Math.random() * 4)](
75
+ tileX,
76
+ tileY,
77
+ tileSize,
78
+ tileConfig
79
+ ),
75
80
  [TileShape.TriangleSE]: (tileX, tileY, tileSize, tileConfig) => /* @__PURE__ */ jsx(
76
81
  "path",
77
82
  {
@@ -158,7 +163,12 @@ const TileTemplates = {
158
163
  },
159
164
  `tile-${tileX}-${tileY}`
160
165
  ),
161
- [TileShape.CaretRand]: (tileX, tileY, tileSize, tileConfig) => TileTemplates[TileShape.CaretN + Math.floor(Math.random() * 4)](tileX, tileY, tileSize, tileConfig),
166
+ [TileShape.CaretRand]: (tileX, tileY, tileSize, tileConfig) => TileTemplates[TileShape.CaretN + Math.floor(Math.random() * 4)](
167
+ tileX,
168
+ tileY,
169
+ tileSize,
170
+ tileConfig
171
+ ),
162
172
  [TileShape.PieSE]: (tileX, tileY, tileSize, tileConfig) => /* @__PURE__ */ jsx(
163
173
  "path",
164
174
  {
@@ -199,7 +209,12 @@ const TileTemplates = {
199
209
  },
200
210
  `tile-${tileX}-${tileY}`
201
211
  ),
202
- [TileShape.PieRand]: (tileX, tileY, tileSize, tileConfig) => TileTemplates[TileShape.PieSE + Math.floor(Math.random() * 4)](tileX, tileY, tileSize, tileConfig)
212
+ [TileShape.PieRand]: (tileX, tileY, tileSize, tileConfig) => TileTemplates[TileShape.PieSE + Math.floor(Math.random() * 4)](
213
+ tileX,
214
+ tileY,
215
+ tileSize,
216
+ tileConfig
217
+ )
203
218
  };
204
219
  const generateIconPattern = (width, height, tileConfig) => {
205
220
  const pattern = [];
@@ -211,10 +226,11 @@ const generateIconPattern = (width, height, tileConfig) => {
211
226
  }
212
227
  return pattern;
213
228
  };
229
+ const itemShape = (shape) => typeof shape === "string" ? TileShape[shape] : shape;
214
230
  const generateTiles = (pattern, tileSize, tileClassName) => pattern.map(
215
231
  (rows, y) => rows.map((item, x) => {
216
232
  const tileConfig = typeof item === "object" ? { className: cn(tileClassName, item.className), scale: item.scale ?? 1, shape: item.shape } : { className: tileClassName, scale: 1, shape: item };
217
- return TileTemplates[tileConfig.shape](x, y, tileSize, tileConfig);
233
+ return TileTemplates[itemShape(tileConfig.shape)](x, y, tileSize, tileConfig);
218
234
  })
219
235
  ).flat();
220
236
  export {
@@ -26,7 +26,9 @@ export declare const TileShape: {
26
26
  readonly PieNE: 24;
27
27
  readonly PieRand: 25;
28
28
  };
29
- export type TileShape = (typeof TileShape)[keyof typeof TileShape];
29
+ export type TileShapeKeys = keyof typeof TileShape;
30
+ export type TileShapeValue = (typeof TileShape)[TileShapeKeys];
31
+ export type TileShape = TileShapeKeys | TileShapeValue;
30
32
  export interface TileConfig {
31
33
  shape: TileShape;
32
34
  scale?: number;
@@ -8,10 +8,10 @@ const overlayVariants = cva("absolute w-fit h-fit z-1 overflow-hidden p-0.25", {
8
8
  b: "bottom-0 left-1/2 -translate-x-1/2",
9
9
  l: "top-1/2 left-0 -translate-y-1/2",
10
10
  r: "top-1/2 right-0 -translate-y-1/2",
11
- tl: "top-0 left-0 rounded-tl-container",
12
- tr: "top-0 right-0 rounded-tr-container",
13
- bl: "bottom-0 left-0 rounded-bl-container",
14
- br: "bottom-0 right-0 rounded-br-container",
11
+ tl: "top-0 left-0",
12
+ tr: "top-0 right-0",
13
+ bl: "bottom-0 left-0",
14
+ br: "bottom-0 right-0",
15
15
  c: "top-1/2 left-1/2 -translate-1/2"
16
16
  }
17
17
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bccampus/ui-components",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "type": "module",
5
5
  "packageManager": "yarn@4.10.3",
6
6
  "exports": {
@@ -0,0 +1,61 @@
1
+ import { CompositeComponent } from "./composite-component";
2
+ import { useCallback, useRef } from "react";
3
+ import { CompositeDataItem } from "./CompositeDataItem";
4
+ import type { BaseCompositeProps } from "./types";
5
+ import { useKeyboardEvent } from "@/hooks/use-keyboard-event";
6
+
7
+ export function LayoutGrid<T extends object>({ data, ...props }: BaseCompositeProps<T>) {
8
+ const compositeRef = useRef<HTMLDivElement>(null);
9
+
10
+ const focusElement = useCallback(() => {
11
+ const itemKey = data.focusProvider.focusedItem.get()?.key;
12
+
13
+ if (itemKey && compositeRef.current) {
14
+ const focusedItemEl = compositeRef.current.querySelector<HTMLDivElement>(`[data-key="${itemKey}"]`);
15
+ if (focusedItemEl) focusedItemEl.focus();
16
+ }
17
+ }, [data]);
18
+
19
+ const handleKeyboardEvent = useKeyboardEvent({
20
+ ArrowUp: () => {
21
+ data.focusProvider.focusUp();
22
+ focusElement();
23
+ },
24
+ ArrowDown: () => {
25
+ data.focusProvider.focusDown();
26
+ focusElement();
27
+ },
28
+ Home: () => {
29
+ data.focusProvider.focusToFirst();
30
+ focusElement();
31
+ },
32
+ End: () => {
33
+ data.focusProvider.focusToLast();
34
+ focusElement();
35
+ },
36
+ Space: () => {
37
+ data.selectionProvider?.toggleSelect();
38
+ focusElement();
39
+ },
40
+ });
41
+
42
+ const handleItemMouseEvent = useCallback(
43
+ (item: CompositeDataItem<T>) => {
44
+ data.focusProvider.focus(item.key);
45
+ data.selectionProvider?.toggleSelect(item);
46
+ focusElement();
47
+ },
48
+ [data.focusProvider, data.selectionProvider, focusElement]
49
+ );
50
+
51
+ return (
52
+ <CompositeComponent
53
+ ref={compositeRef}
54
+ variant="listbox"
55
+ data={data}
56
+ onKeyDown={handleKeyboardEvent}
57
+ itemMouseEventHandler={handleItemMouseEvent}
58
+ {...props}
59
+ />
60
+ );
61
+ }
@@ -1,5 +1,5 @@
1
1
  import type { JSX } from "react";
2
- import type { TileConfig } from "./types";
2
+ import type { TileConfig, TileShapeValue } from "./types";
3
3
  import { cn } from "@/lib/utils";
4
4
  import { TileShape } from "./types";
5
5
 
@@ -21,7 +21,7 @@ const randomSet = [
21
21
  type TileTemplatesConfig = TileConfig & Required<Pick<TileConfig, "scale">>;
22
22
 
23
23
  const TileTemplates: Record<
24
- TileShape,
24
+ TileShapeValue,
25
25
  (tileX: number, tileY: number, tileSize: number, tileConfig: TileTemplatesConfig) => JSX.Element | null
26
26
  > = {
27
27
  [TileShape.Blank]: () => null,
@@ -85,7 +85,12 @@ const TileTemplates: Record<
85
85
  );
86
86
  },
87
87
  [TileShape.RandBasic]: (tileX, tileY, tileSize, tileConfig) =>
88
- TileTemplates[(TileShape.Square + Math.floor(Math.random() * 4)) as TileShape](tileX, tileY, tileSize, tileConfig),
88
+ TileTemplates[(TileShape.Square + Math.floor(Math.random() * 4)) as TileShapeValue](
89
+ tileX,
90
+ tileY,
91
+ tileSize,
92
+ tileConfig
93
+ ),
89
94
 
90
95
  [TileShape.TriangleSE]: (tileX, tileY, tileSize, tileConfig) => (
91
96
  <path
@@ -124,7 +129,7 @@ const TileTemplates: Record<
124
129
  />
125
130
  ),
126
131
  [TileShape.TriangleRand]: (tileX, tileY, tileSize, tileConfig) =>
127
- TileTemplates[(TileShape.TriangleSE + Math.floor(Math.random() * 4)) as TileShape](
132
+ TileTemplates[(TileShape.TriangleSE + Math.floor(Math.random() * 4)) as TileShapeValue](
128
133
  tileX,
129
134
  tileY,
130
135
  tileSize,
@@ -168,7 +173,12 @@ const TileTemplates: Record<
168
173
  />
169
174
  ),
170
175
  [TileShape.CaretRand]: (tileX, tileY, tileSize, tileConfig) =>
171
- TileTemplates[(TileShape.CaretN + Math.floor(Math.random() * 4)) as TileShape](tileX, tileY, tileSize, tileConfig),
176
+ TileTemplates[(TileShape.CaretN + Math.floor(Math.random() * 4)) as TileShapeValue](
177
+ tileX,
178
+ tileY,
179
+ tileSize,
180
+ tileConfig
181
+ ),
172
182
 
173
183
  [TileShape.PieSE]: (tileX, tileY, tileSize, tileConfig) => (
174
184
  <path
@@ -213,7 +223,12 @@ const TileTemplates: Record<
213
223
  />
214
224
  ),
215
225
  [TileShape.PieRand]: (tileX, tileY, tileSize, tileConfig) =>
216
- TileTemplates[(TileShape.PieSE + Math.floor(Math.random() * 4)) as TileShape](tileX, tileY, tileSize, tileConfig),
226
+ TileTemplates[(TileShape.PieSE + Math.floor(Math.random() * 4)) as TileShapeValue](
227
+ tileX,
228
+ tileY,
229
+ tileSize,
230
+ tileConfig
231
+ ),
217
232
  };
218
233
 
219
234
  export const generateIconPattern = (width: number, height: number, tileConfig: TileShape | TileConfig) => {
@@ -228,6 +243,8 @@ export const generateIconPattern = (width: number, height: number, tileConfig: T
228
243
  return pattern;
229
244
  };
230
245
 
246
+ const itemShape = (shape: TileShape) => (typeof shape === "string" ? TileShape[shape] : shape);
247
+
231
248
  export const generateTiles = (pattern: (TileShape | TileConfig)[][], tileSize: number, tileClassName?: string) =>
232
249
  pattern
233
250
  .map((rows, y) =>
@@ -237,7 +254,7 @@ export const generateTiles = (pattern: (TileShape | TileConfig)[][], tileSize: n
237
254
  ? { className: cn(tileClassName, item.className), scale: item.scale ?? 1, shape: item.shape }
238
255
  : { className: tileClassName, scale: 1, shape: item };
239
256
 
240
- return TileTemplates[tileConfig.shape](x, y, tileSize, tileConfig);
257
+ return TileTemplates[itemShape(tileConfig.shape)](x, y, tileSize, tileConfig);
241
258
  })
242
259
  )
243
260
  .flat();
@@ -28,7 +28,9 @@ export const TileShape = {
28
28
  PieRand: 25,
29
29
  } as const;
30
30
 
31
- export type TileShape = (typeof TileShape)[keyof typeof TileShape];
31
+ export type TileShapeKeys = keyof typeof TileShape;
32
+ export type TileShapeValue = (typeof TileShape)[TileShapeKeys];
33
+ export type TileShape = TileShapeKeys | TileShapeValue;
32
34
 
33
35
  export interface TileConfig {
34
36
  shape: TileShape;
@@ -8,10 +8,10 @@ const overlayVariants = cva("absolute w-fit h-fit z-1 overflow-hidden p-0.25", {
8
8
  b: "bottom-0 left-1/2 -translate-x-1/2",
9
9
  l: "top-1/2 left-0 -translate-y-1/2",
10
10
  r: "top-1/2 right-0 -translate-y-1/2",
11
- tl: "top-0 left-0 rounded-tl-container",
12
- tr: "top-0 right-0 rounded-tr-container",
13
- bl: "bottom-0 left-0 rounded-bl-container",
14
- br: "bottom-0 right-0 rounded-br-container",
11
+ tl: "top-0 left-0",
12
+ tr: "top-0 right-0",
13
+ bl: "bottom-0 left-0",
14
+ br: "bottom-0 right-0",
15
15
  c: "top-1/2 left-1/2 -translate-1/2",
16
16
  },
17
17
  },