@bccampus/ui-components 0.4.0 → 0.4.2

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 (37) hide show
  1. package/dist/AbstractFocusProvider-CxvlcEki.js +29 -0
  2. package/dist/AbstractSelectionProvider-BtaROstC.js +30 -0
  3. package/dist/CompositeDataItem-DuHOHCWy.js +158 -0
  4. package/dist/ListboxFocusProvider.d.ts +149 -0
  5. package/dist/ListboxFocusProvider.js +53 -0
  6. package/dist/MultipleSelectionProvider.d.ts +141 -0
  7. package/dist/MultipleSelectionProvider.js +19 -0
  8. package/dist/SingleSelectionProvider.d.ts +141 -0
  9. package/dist/SingleSelectionProvider.js +23 -0
  10. package/dist/composite-component-DSUbd1XS.js +122 -0
  11. package/dist/composite.d.ts +108 -51
  12. package/dist/composite.js +57 -447
  13. package/dist/icon-generator-tuhuqdpL.js +76 -0
  14. package/dist/icon-generator.d.ts +11 -4
  15. package/dist/icon-generator.js +4 -74
  16. package/dist/listbox.d.ts +171 -0
  17. package/dist/listbox.js +76 -0
  18. package/dist/masked-image-generator.js +7 -7
  19. package/dist/ui-components.js +5 -5
  20. package/package.json +5 -1
  21. package/src/components/ui/composite/CompositeData.ts +22 -114
  22. package/src/components/ui/composite/FocusProvider/AbstractFocusProvider.ts +83 -0
  23. package/src/components/ui/composite/FocusProvider/ListboxFocusProvider.ts +74 -0
  24. package/src/components/ui/composite/SelectionProvider/AbstractSelectionProvider.ts +45 -0
  25. package/src/components/ui/composite/SelectionProvider/MultipleSelectionProvider.ts +28 -0
  26. package/src/components/ui/composite/SelectionProvider/SingleSelectionProvider.ts +37 -0
  27. package/src/components/ui/composite/composite-component-item.tsx +12 -10
  28. package/src/components/ui/composite/composite-component.tsx +39 -68
  29. package/src/components/ui/composite/index.ts +4 -1
  30. package/src/components/ui/composite/listbox.tsx +61 -0
  31. package/src/components/ui/composite/types.ts +51 -30
  32. package/src/components/ui/icon-generator/index.ts +2 -0
  33. package/src/hooks/use-keyboard-event.ts +31 -42
  34. package/vite.config.ts +6 -2
  35. package/src/components/ui/composite/composite-data-context.tsx +0 -31
  36. /package/dist/{igenerate-tiles.d.ts → generate-tiles.d.ts} +0 -0
  37. /package/dist/{igenerate-tiles.js → generate-tiles.js} +0 -0
@@ -1,52 +1,38 @@
1
1
  import type { KeyboardEvent, KeyboardEventHandler } from 'react';
2
2
  import { useMemo } from 'react';
3
3
 
4
- const MODIFIER_KEYS = new Set(['ctrl', 'shift', 'alt', 'meta']);
5
-
6
- const KEY_MAPPINGS: Record<string, string> = {
7
- ' ': 'space',
8
- };
9
-
10
- export interface KeyBindings {
4
+ interface KeyBindings {
11
5
  [sequence: string]: (event: KeyboardEvent) => void;
12
6
  }
13
-
14
7
  interface KeybindingLookupItem {
15
- sequence: Set<string>;
8
+ sequence: RegExp;
16
9
  handler: (event: KeyboardEvent) => void;
17
10
  }
11
+ const MODIFIER_KEYS = new Set(["ctrl", "shift", "alt", "meta"]);
12
+
13
+ const KEY_MAPPINGS: Record<string, string> = {
14
+ " ": "space",
15
+ };
18
16
 
19
17
  interface UseKeyboardEventOptions {
20
18
  eventKeyProp: 'key' | 'code';
21
19
  }
22
20
 
23
- function isSequenceEqual<T>(sequenceA: Set<T>, sequenceB: Set<T>) {
24
- if (sequenceA.size !== sequenceB.size) return false;
25
-
26
- for (const element of sequenceB) {
27
- if (!sequenceA.has(element)) return false;
28
- }
29
-
30
- return true;
31
- }
32
-
33
21
  function parseKeybindings(bindings: KeyBindings) {
34
22
  const parsedKeybindings: KeybindingLookupItem[] = [];
35
23
  for (const [sequence, handler] of Object.entries(bindings)) {
36
24
  const parsedSequence = sequence
37
25
  .toLowerCase()
38
26
  .trim()
39
- .split(/\s*\+\s*/);
27
+ .split(/\s*\+\s*/g);
40
28
 
41
29
  if (parsedSequence.length === 1 && MODIFIER_KEYS.has(parsedSequence[0])) {
42
- console.error(`[useKeyboardEvent] \`${sequence}\`: A key sequence cannot be only a modifier key.`);
43
- }
44
- else if (parsedSequence.includes('')) {
45
- console.error(`[useKeyboardEvent] \`${sequence}\`: Unknown key defined in the sequence.`);
46
- }
47
- else {
30
+ console.error(`[useKeyboardEvent] '${sequence}': A key sequence cannot be only a modifier key.`);
31
+ } else if (parsedSequence.includes("")) {
32
+ console.error(`[useKeyboardEvent] '${sequence}': Invalid key sequence defined in the sequence.`);
33
+ } else {
48
34
  parsedKeybindings.push({
49
- sequence: new Set(parsedSequence),
35
+ sequence: new RegExp("^" + parsedSequence.join("\\+") + "$"),
50
36
  handler,
51
37
  });
52
38
  }
@@ -68,21 +54,22 @@ export function keyboardEventHandler(
68
54
  const keyBindings = parseKeybindings(bindings);
69
55
 
70
56
  return (event: KeyboardEvent) => {
71
- const keySequence = new Set<string>();
72
57
  const eventKey = event[_options.eventKeyProp];
58
+ const keySequence: string[] = [];
73
59
 
74
- if (event.ctrlKey) keySequence.add('ctrl');
60
+ if (event.ctrlKey) keySequence.push("ctrl");
75
61
 
76
- if (event.shiftKey) keySequence.add('shift');
62
+ if (event.shiftKey) keySequence.push("shift");
77
63
 
78
- if (event.altKey) keySequence.add('alt');
64
+ if (event.altKey) keySequence.push("alt");
79
65
 
80
- if (event.metaKey) keySequence.add('meta');
66
+ if (event.metaKey) keySequence.push("meta");
81
67
 
82
- if (!KEY_MAPPINGS[eventKey]) keySequence.add(eventKey.toLowerCase());
83
- else keySequence.add(KEY_MAPPINGS[eventKey]);
68
+ if (!KEY_MAPPINGS[eventKey]) keySequence.push(eventKey.toLowerCase());
69
+ else keySequence.push(KEY_MAPPINGS[eventKey]);
84
70
 
85
- const matchedSequence = keyBindings.find(keyBinding => isSequenceEqual(keySequence, keyBinding.sequence));
71
+ const matchedSequence = keyBindings.find((keyBinding) => keyBinding.sequence.test(keySequence.join("+")));
72
+
86
73
  if (matchedSequence) {
87
74
  event.preventDefault();
88
75
  event.stopPropagation();
@@ -91,16 +78,18 @@ export function keyboardEventHandler(
91
78
  };
92
79
  }
93
80
 
81
+
94
82
  /**
95
83
  * Returns a `KeyboardEventHandler`
96
- * that checks the defined key binding sequences against a keyboard event
84
+ * that checks the defined key sequences against a keyboard event
97
85
  * and executes the handler of the first matched key binding.
98
- *
99
- * Limitations:
100
- * - Space character (` `) cannot be used in the key sequences.
101
- * Use the `space` keyword instead.
102
- * - Plus character (`+`) cannot be used in the key sequences.
103
- * Use `shit + =` instead.
86
+ *
87
+ * Key Sequence Rules:
88
+ * - Multiple key must be seperated by `+`
89
+ * - Only the following modifier key values as allowed: ctrl, shift, alt, meta
90
+ * - Modifier key must followed by a key
91
+ * - Space character (` `) cannot be used in the key sequences. Use the `space` keyword instead.
92
+ * - Plus character (`+`) cannot be used in the key sequences. Use the `shit + =` sequence instead.
104
93
  *
105
94
  * @example
106
95
  * ```
package/vite.config.ts CHANGED
@@ -21,8 +21,12 @@ export default defineConfig({
21
21
  entry: {
22
22
  'ui-components': path.resolve(__dirname, 'src/components/ui/index.ts'),
23
23
  'composite': path.resolve(__dirname, 'src/components/ui/composite/index.ts'),
24
- 'icon-generator': path.resolve(__dirname, 'src/components/ui/icon-generator/icon-generator.tsx'),
25
- 'igenerate-tiles': path.resolve(__dirname, 'src/components/ui/icon-generator/generate-tiles.tsx'),
24
+ 'listbox': path.resolve(__dirname, 'src/components/ui/composite/listbox.tsx'),
25
+ 'SingleSelectionProvider': path.resolve(__dirname, 'src/components/ui/composite/SelectionProvider/SingleSelectionProvider.ts'),
26
+ 'MultipleSelectionProvider': path.resolve(__dirname, 'src/components/ui/composite/SelectionProvider/MultipleSelectionProvider.ts'),
27
+ 'ListboxFocusProvider': path.resolve(__dirname, 'src/components/ui/composite/FocusProvider/ListboxFocusProvider.ts'),
28
+ 'icon-generator': path.resolve(__dirname, 'src/components/ui/icon-generator/index.ts'),
29
+ 'generate-tiles': path.resolve(__dirname, 'src/components/ui/icon-generator/generate-tiles.tsx'),
26
30
  'masked-image-generator': path.resolve(__dirname, 'src/components/ui/icon-generator/masked-image-generator.tsx'),
27
31
  'caption': path.resolve(__dirname, 'src/components/ui/typography/caption.tsx'),
28
32
  'banner': path.resolve(__dirname, 'src/components/ui/banner.tsx'),
@@ -1,31 +0,0 @@
1
- import { createContext, useContext, useMemo } from "react";
2
- import { CompositeData } from "./CompositeData";
3
- import type { CompositeOptions } from "./types";
4
-
5
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
- const CompositeDataContext = createContext<CompositeData<any> | undefined>(undefined);
7
-
8
- export function useCompositeContext<T extends object>() {
9
- const context = useContext(CompositeDataContext);
10
-
11
- if (!context) {
12
- throw new Error("No CompositeDataContext has been set, use CompositeDataContext to provide a context");
13
- }
14
-
15
- return context as CompositeData<T>;
16
- }
17
-
18
- interface CompositeComponentContextProps<T extends object> extends CompositeOptions {
19
- data: T[];
20
- children: React.ReactNode;
21
- }
22
-
23
- export function CompositeComponentContext<T extends object>({
24
- data,
25
- children,
26
- ...compositeOptions
27
- }: CompositeComponentContextProps<T>) {
28
- const composite = useMemo(() => new CompositeData(data, compositeOptions), [data, compositeOptions]);
29
-
30
- return <CompositeDataContext value={composite}>{children}</CompositeDataContext>;
31
- }
File without changes