@nascentdigital/funnel-ui 4.5.2 → 4.5.3

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 (66) hide show
  1. package/dist/client/hooks/breakpoint/BreakpointContainer.d.ts +1 -1
  2. package/dist/client/hooks/breakpoint/BreakpointContainer.js +3 -1
  3. package/dist/client/interaction/index.d.ts +0 -6
  4. package/dist/client/interaction/index.js +0 -6
  5. package/dist/server/blocks/Block.js +2 -2
  6. package/dist/server/blocks/Message.js +2 -1
  7. package/dist/server/blocks/Testimonial.js +13 -10
  8. package/dist/server/blocks/Testimonials.d.ts +35 -35
  9. package/dist/server/blocks/Testimonials.js +21 -66
  10. package/dist/server/blocks/index.d.ts +1 -0
  11. package/dist/server/blocks/index.js +1 -0
  12. package/dist/server/fields/CallToActions.d.ts +12 -0
  13. package/dist/server/fields/CallToActions.js +27 -0
  14. package/dist/server/fields/index.d.ts +1 -0
  15. package/dist/server/fields/index.js +1 -0
  16. package/dist/server/panels/BlockPanel.js +1 -2
  17. package/dist/server/panels/MessagePanel.d.ts +2 -6
  18. package/dist/server/panels/MessagePanel.js +2 -9
  19. package/dist/server/panels/TestimonialPanel.d.ts +44 -18
  20. package/dist/server/panels/TestimonialPanel.js +44 -19
  21. package/dist/server/panels/VisualPanel.d.ts +1 -1
  22. package/package.json +2 -2
  23. package/dist/client/interaction/Popup.d.ts +0 -36
  24. package/dist/client/interaction/Popup.js +0 -244
  25. package/dist/client/interaction/Tooltip.d.ts +0 -16
  26. package/dist/client/interaction/Tooltip.js +0 -122
  27. package/dist/client/interaction/UILevel.d.ts +0 -1
  28. package/dist/client/interaction/UILevel.js +0 -2
  29. package/dist/client/interaction/backdrop/BackdropContainer.d.ts +0 -5
  30. package/dist/client/interaction/backdrop/BackdropContainer.js +0 -114
  31. package/dist/client/interaction/backdrop/BackdropContext.d.ts +0 -8
  32. package/dist/client/interaction/backdrop/BackdropContext.js +0 -6
  33. package/dist/client/interaction/backdrop/BackdropEvent.d.ts +0 -64
  34. package/dist/client/interaction/backdrop/BackdropEvent.js +0 -92
  35. package/dist/client/interaction/backdrop/index.d.ts +0 -4
  36. package/dist/client/interaction/backdrop/index.js +0 -20
  37. package/dist/client/interaction/backdrop/useBackdrop.d.ts +0 -13
  38. package/dist/client/interaction/backdrop/useBackdrop.js +0 -58
  39. package/dist/client/interaction/backdrop/useBackdropClick.d.ts +0 -2
  40. package/dist/client/interaction/backdrop/useBackdropClick.js +0 -21
  41. package/dist/client/interaction/backdrop/useBackdropVisible.d.ts +0 -1
  42. package/dist/client/interaction/backdrop/useBackdropVisible.js +0 -30
  43. package/dist/client/interaction/focus/FocusArea.d.ts +0 -10
  44. package/dist/client/interaction/focus/FocusArea.js +0 -38
  45. package/dist/client/interaction/focus/FocusContext.d.ts +0 -7
  46. package/dist/client/interaction/focus/FocusContext.js +0 -7
  47. package/dist/client/interaction/focus/FocusController.d.ts +0 -9
  48. package/dist/client/interaction/focus/FocusController.js +0 -40
  49. package/dist/client/interaction/focus/FocusService.d.ts +0 -20
  50. package/dist/client/interaction/focus/FocusService.js +0 -204
  51. package/dist/client/interaction/focus/LinkedList.d.ts +0 -18
  52. package/dist/client/interaction/focus/LinkedList.js +0 -122
  53. package/dist/client/interaction/focus/index.d.ts +0 -2
  54. package/dist/client/interaction/focus/index.js +0 -18
  55. package/dist/client/interaction/focus/useFocusService.d.ts +0 -2
  56. package/dist/client/interaction/focus/useFocusService.js +0 -14
  57. package/dist/client/interaction/modal/Modal.d.ts +0 -29
  58. package/dist/client/interaction/modal/Modal.js +0 -136
  59. package/dist/client/interaction/modal/ModalContainer.d.ts +0 -5
  60. package/dist/client/interaction/modal/ModalContainer.js +0 -104
  61. package/dist/client/interaction/modal/ModalContext.d.ts +0 -8
  62. package/dist/client/interaction/modal/ModalContext.js +0 -6
  63. package/dist/client/interaction/modal/ModalEvent.d.ts +0 -39
  64. package/dist/client/interaction/modal/ModalEvent.js +0 -53
  65. package/dist/client/interaction/modal/index.d.ts +0 -2
  66. package/dist/client/interaction/modal/index.js +0 -18
@@ -1,92 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BackdropEvent = void 0;
4
- // extension
5
- var BackdropEvent;
6
- (function (BackdropEvent) {
7
- let Show;
8
- (function (Show) {
9
- function guard(event) {
10
- return event.action === 'show';
11
- }
12
- Show.guard = guard;
13
- function create(dependants, dependent, options) {
14
- return {
15
- action: 'show',
16
- dependent,
17
- dependants,
18
- options
19
- };
20
- }
21
- Show.create = create;
22
- })(Show = BackdropEvent.Show || (BackdropEvent.Show = {}));
23
- let Hide;
24
- (function (Hide) {
25
- function guard(event) {
26
- return event.action === 'hide';
27
- }
28
- Hide.guard = guard;
29
- function create() {
30
- return {
31
- action: 'hide'
32
- };
33
- }
34
- Hide.create = create;
35
- })(Hide = BackdropEvent.Hide || (BackdropEvent.Hide = {}));
36
- let Click;
37
- (function (Click) {
38
- function guard(event) {
39
- return event.action === 'click';
40
- }
41
- Click.guard = guard;
42
- function create() {
43
- return {
44
- action: 'click'
45
- };
46
- }
47
- Click.create = create;
48
- })(Click = BackdropEvent.Click || (BackdropEvent.Click = {}));
49
- let FocusChange;
50
- (function (FocusChange) {
51
- function guard(event) {
52
- return event.action === 'focusChange';
53
- }
54
- FocusChange.guard = guard;
55
- function create(dependent) {
56
- return {
57
- action: 'focusChange',
58
- dependent
59
- };
60
- }
61
- FocusChange.create = create;
62
- })(FocusChange = BackdropEvent.FocusChange || (BackdropEvent.FocusChange = {}));
63
- let Capture;
64
- (function (Capture) {
65
- function guard(event) {
66
- return event.action === 'capture';
67
- }
68
- Capture.guard = guard;
69
- function create(id, options) {
70
- return {
71
- id,
72
- action: 'capture',
73
- options
74
- };
75
- }
76
- Capture.create = create;
77
- })(Capture = BackdropEvent.Capture || (BackdropEvent.Capture = {}));
78
- let Release;
79
- (function (Release) {
80
- function guard(event) {
81
- return event.action === 'release';
82
- }
83
- Release.guard = guard;
84
- function create(id) {
85
- return {
86
- id,
87
- action: 'release'
88
- };
89
- }
90
- Release.create = create;
91
- })(Release = BackdropEvent.Release || (BackdropEvent.Release = {}));
92
- })(BackdropEvent || (exports.BackdropEvent = BackdropEvent = {}));
@@ -1,4 +0,0 @@
1
- export * from './BackdropContainer';
2
- export * from './useBackdrop';
3
- export * from './useBackdropClick';
4
- export * from './useBackdropVisible';
@@ -1,20 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./BackdropContainer"), exports);
18
- __exportStar(require("./useBackdrop"), exports);
19
- __exportStar(require("./useBackdropClick"), exports);
20
- __exportStar(require("./useBackdropVisible"), exports);
@@ -1,13 +0,0 @@
1
- import { Subject } from 'rxjs';
2
- import { BackdropEvent } from './BackdropEvent';
3
- export declare function useBackdrop(): BackdropProxy;
4
- export declare class BackdropProxy {
5
- readonly id: BackdropEvent.DependantId;
6
- private readonly _eventBus;
7
- private _focused;
8
- constructor(id: BackdropEvent.DependantId, _eventBus: Subject<BackdropEvent>);
9
- get focused(): boolean;
10
- set focused(value: boolean);
11
- show(options?: BackdropEvent.Options): void;
12
- hide(): void;
13
- }
@@ -1,58 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BackdropProxy = void 0;
4
- exports.useBackdrop = useBackdrop;
5
- const react_1 = require("react");
6
- const hooks_1 = require("../../hooks");
7
- const BackdropContext_1 = require("./BackdropContext");
8
- const BackdropEvent_1 = require("./BackdropEvent");
9
- // hook
10
- function useBackdrop() {
11
- // bind context + state
12
- const touch = (0, hooks_1.useTouch)();
13
- const { eventBus } = (0, react_1.useContext)(BackdropContext_1.BackdropContext);
14
- const id = (0, react_1.useId)();
15
- const proxy = (0, react_1.useMemo)(() => new BackdropProxy(id, eventBus), [id, eventBus]);
16
- // listen to determine if "this" backdrop is focused (meaning this reference to it)
17
- (0, react_1.useEffect)(() => {
18
- // subscribe to show/focusChange events
19
- const subscription = eventBus
20
- .subscribe(event => {
21
- // handle backdrop being shown or focus changing
22
- if (BackdropEvent_1.BackdropEvent.Show.guard(event) || BackdropEvent_1.BackdropEvent.FocusChange.guard(event)) {
23
- proxy.focused = event.dependent === id;
24
- touch();
25
- }
26
- // or if this backdrop is hidden
27
- else if (BackdropEvent_1.BackdropEvent.Hide.guard(event)) {
28
- proxy.focused = false;
29
- touch();
30
- }
31
- });
32
- // unmount
33
- return () => subscription.unsubscribe();
34
- }, [touch, eventBus, id, proxy]);
35
- // return proxy
36
- return proxy;
37
- }
38
- // proxy
39
- class BackdropProxy {
40
- constructor(id, _eventBus) {
41
- this.id = id;
42
- this._eventBus = _eventBus;
43
- this._focused = false;
44
- }
45
- get focused() {
46
- return this._focused;
47
- }
48
- set focused(value) {
49
- this._focused = value;
50
- }
51
- show(options) {
52
- this._eventBus.next(BackdropEvent_1.BackdropEvent.Capture.create(this.id, options !== null && options !== void 0 ? options : {}));
53
- }
54
- hide() {
55
- this._eventBus.next(BackdropEvent_1.BackdropEvent.Release.create(this.id));
56
- }
57
- }
58
- exports.BackdropProxy = BackdropProxy;
@@ -1,2 +0,0 @@
1
- import { Callback } from '@nascentdigital/funnel-core';
2
- export declare function useBackdropClick(onClick: Callback.Void): void;
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useBackdropClick = useBackdropClick;
4
- const react_1 = require("react");
5
- const rxjs_1 = require("rxjs");
6
- const BackdropContext_1 = require("./BackdropContext");
7
- const BackdropEvent_1 = require("./BackdropEvent");
8
- // hook
9
- function useBackdropClick(onClick) {
10
- // bind context
11
- const { eventBus } = (0, react_1.useContext)(BackdropContext_1.BackdropContext);
12
- // subscribe for click actions
13
- (0, react_1.useEffect)(() => {
14
- // subscribe
15
- const subscription = eventBus
16
- .pipe((0, rxjs_1.filter)(BackdropEvent_1.BackdropEvent.Click.guard))
17
- .subscribe(() => onClick());
18
- // unsubscribe on unmount
19
- return () => subscription.unsubscribe();
20
- }, [eventBus, onClick]);
21
- }
@@ -1 +0,0 @@
1
- export declare function useBackdropVisible(): boolean;
@@ -1,30 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useBackdropVisible = useBackdropVisible;
4
- const react_1 = require("react");
5
- const BackdropContext_1 = require("./BackdropContext");
6
- const BackdropEvent_1 = require("./BackdropEvent");
7
- // hook
8
- function useBackdropVisible() {
9
- // bind props + state
10
- const { eventBus } = (0, react_1.useContext)(BackdropContext_1.BackdropContext);
11
- const [visible, setVisible] = (0, react_1.useState)(false);
12
- // listen for events and update
13
- (0, react_1.useEffect)(() => {
14
- // listen on mount
15
- const subscription = eventBus.subscribe(event => {
16
- // handle show/focus as meaning we're visible
17
- if (BackdropEvent_1.BackdropEvent.Show.guard(event) || BackdropEvent_1.BackdropEvent.FocusChange.guard(event)) {
18
- setVisible(true);
19
- }
20
- // or handle hide as not visible
21
- else if (BackdropEvent_1.BackdropEvent.Hide.guard(event)) {
22
- setVisible(false);
23
- }
24
- });
25
- // unsubscribe on unmount
26
- return () => subscription.unsubscribe();
27
- }, [eventBus]);
28
- // return state
29
- return visible;
30
- }
@@ -1,10 +0,0 @@
1
- import { HTMLAttributes } from 'react';
2
- import { HTMLElements } from '../../../types';
3
- export declare function FocusArea<T extends FocusArea.Tag>({ as, children, order, ...props }: FocusArea.Props<T>): import("react/jsx-runtime").JSX.Element;
4
- export declare namespace FocusArea {
5
- type Props<T extends Tag> = Omit<HTMLAttributes<HTMLElements.Standard[T]>, 'tabIndex' | 'onFocus'> & {
6
- as: T;
7
- order: number;
8
- };
9
- type Tag = HTMLElements.Standard.Container;
10
- }
@@ -1,38 +0,0 @@
1
- 'use client';
2
- "use strict";
3
- var __rest = (this && this.__rest) || function (s, e) {
4
- var t = {};
5
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
6
- t[p] = s[p];
7
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
8
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
9
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
10
- t[p[i]] = s[p[i]];
11
- }
12
- return t;
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.FocusArea = FocusArea;
16
- const jsx_runtime_1 = require("react/jsx-runtime");
17
- const react_1 = require("react");
18
- const hooks_1 = require("../../hooks");
19
- const useFocusService_1 = require("./useFocusService");
20
- function FocusArea(_a) {
21
- var { as, children, order } = _a, props = __rest(_a, ["as", "children", "order"]);
22
- // bind hooks/context
23
- const [ref, element] = (0, hooks_1.useRefElement)();
24
- const focusService = (0, useFocusService_1.useFocusService)();
25
- // register/unregister area
26
- (0, react_1.useEffect)(() => {
27
- // ignore until element is ready
28
- if (!element) {
29
- return;
30
- }
31
- // register with controller
32
- focusService.bindArea(element, { order });
33
- // unregister in unmount
34
- return () => focusService.unbindArea(element);
35
- }, [focusService, element, order]);
36
- // render
37
- return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, react_1.createElement)(as, Object.assign(Object.assign({}, props), { ref }), children) }));
38
- }
@@ -1,7 +0,0 @@
1
- import type { FocusService } from './FocusService';
2
- export declare const FocusContext: import("react").Context<FocusContext.Data>;
3
- export declare namespace FocusContext {
4
- type Data = {
5
- focusService?: FocusService;
6
- };
7
- }
@@ -1,7 +0,0 @@
1
- 'use client';
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.FocusContext = void 0;
5
- const react_1 = require("react");
6
- // context
7
- exports.FocusContext = (0, react_1.createContext)({});
@@ -1,9 +0,0 @@
1
- import { HTMLAttributes } from 'react';
2
- import { HTMLElements } from '../../../types';
3
- export declare function FocusController<T extends FocusController.Tag>({ children, as, ...props }: FocusController.Props<T>): import("react/jsx-runtime").JSX.Element;
4
- export declare namespace FocusController {
5
- type Props<T extends Tag> = Omit<HTMLAttributes<HTMLElements.Standard[T]>, 'tabIndex'> & {
6
- as: T;
7
- };
8
- type Tag = HTMLElements.Standard.Container;
9
- }
@@ -1,40 +0,0 @@
1
- "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.FocusController = FocusController;
15
- const jsx_runtime_1 = require("react/jsx-runtime");
16
- const react_1 = require("react");
17
- const hooks_1 = require("../../hooks");
18
- const FocusContext_1 = require("./FocusContext");
19
- const FocusService_1 = require("./FocusService");
20
- function FocusController(_a) {
21
- var { children, as } = _a, props = __rest(_a, ["children", "as"]);
22
- // bind state/hooks
23
- const [ref, rootElement] = (0, hooks_1.useRefElement)();
24
- const [lastGuardRef, lastGuardElement] = (0, hooks_1.useRefElement)();
25
- const focusService = (0, react_1.useMemo)(() => new FocusService_1.FocusService(), []);
26
- const context = (0, react_1.useMemo)(() => ({ focusService }), [focusService]);
27
- // bind service
28
- (0, react_1.useEffect)(() => {
29
- // ignore until element is ready
30
- if (!rootElement || !lastGuardElement) {
31
- return;
32
- }
33
- // initialize new service
34
- focusService.initialize(rootElement, lastGuardElement);
35
- // unregister in unmount
36
- return () => focusService.finalize();
37
- }, [focusService, rootElement, lastGuardElement]);
38
- // render
39
- return ((0, jsx_runtime_1.jsx)(FocusContext_1.FocusContext.Provider, { value: context, children: (0, react_1.createElement)(as, Object.assign({ ref, tabIndex: '0' }, props), (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [children, (0, jsx_runtime_1.jsx)("div", { ref: lastGuardRef, className: "outline-none", "aria-hidden": true, tabIndex: 0 })] })) }));
40
- }
@@ -1,20 +0,0 @@
1
- export declare class FocusService {
2
- private _rootElement?;
3
- private _lastGuardElement?;
4
- private readonly _areaNodes;
5
- private _focusedAreaNode?;
6
- constructor();
7
- initialize(root: HTMLElement, lastGuard: HTMLElement): void;
8
- finalize(): void;
9
- bindArea(area: HTMLElement, { order }?: FocusService.AreaOptions): void;
10
- unbindArea(area: HTMLElement): void;
11
- private onRootFocus;
12
- private onAreaFocus;
13
- private onLastGuardFocus;
14
- private focusOutside;
15
- }
16
- export declare namespace FocusService {
17
- type AreaOptions = {
18
- order?: number;
19
- };
20
- }
@@ -1,204 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FocusService = void 0;
4
- const funnel_core_1 = require("@nascentdigital/funnel-core");
5
- const LinkedList_1 = require("./LinkedList");
6
- class FocusService {
7
- constructor() {
8
- // instance variables
9
- this._areaNodes = new LinkedList_1.SortedLinkedList();
10
- // bind methods
11
- this.onAreaFocus = this.onAreaFocus.bind(this);
12
- this.onRootFocus = this.onRootFocus.bind(this);
13
- this.onLastGuardFocus = this.onLastGuardFocus.bind(this);
14
- }
15
- initialize(root, lastGuard) {
16
- // capture root and last guard
17
- this._rootElement = root;
18
- this._lastGuardElement = lastGuard;
19
- // bind listeners
20
- this._rootElement.addEventListener('focusin', this.onRootFocus);
21
- this._lastGuardElement.addEventListener('focusin', this.onLastGuardFocus);
22
- }
23
- finalize() {
24
- var _a, _b;
25
- // clear listeners
26
- (_a = this._rootElement) === null || _a === void 0 ? void 0 : _a.removeEventListener('focusin', this.onRootFocus);
27
- (_b = this._lastGuardElement) === null || _b === void 0 ? void 0 : _b.removeEventListener('focusin', this.onLastGuardFocus);
28
- // remove root
29
- delete this._rootElement;
30
- delete this._lastGuardElement;
31
- }
32
- bindArea(area, { order = 0 } = {}) {
33
- // ensure area isn't already bound
34
- let pointer = this._areaNodes.head;
35
- while (pointer) {
36
- if (pointer.area === area) {
37
- console.warn('[FocusService.ts]: area is already bound');
38
- return;
39
- }
40
- pointer = pointer.next;
41
- }
42
- // update the node links
43
- this._areaNodes.insert(new AreaNode(area, order));
44
- // initialize area
45
- area.addEventListener('focusin', this.onAreaFocus);
46
- area.tabIndex = 0;
47
- }
48
- unbindArea(area) {
49
- // find element (or skip)
50
- const { _areaNodes } = this;
51
- const node = _areaNodes.find(node => node.area === area);
52
- if (!node) {
53
- console.warn('[FocusService]: area not found to unbind');
54
- return;
55
- }
56
- // unregister listeners
57
- area.removeEventListener('focusin', this.onAreaFocus);
58
- // remove the element from list
59
- _areaNodes.remove(node);
60
- }
61
- onRootFocus(e) {
62
- var _a;
63
- // skip events bubbled up from the children
64
- if (e.target !== e.currentTarget) {
65
- return;
66
- }
67
- // skip if not focused through keyboard
68
- // TODO: handle mouse click focus
69
- const element = e.target;
70
- if (!element.matches(':focus-visible')) {
71
- return;
72
- }
73
- // focus the first tab-able element
74
- const focusedArea = (_a = this._areaNodes.head) === null || _a === void 0 ? void 0 : _a.focusNext(true);
75
- if (focusedArea) {
76
- this._focusedAreaNode = focusedArea;
77
- return;
78
- }
79
- // else, focus outside the container
80
- this.focusOutside('forward');
81
- }
82
- onAreaFocus(e) {
83
- var _a, _b, _c;
84
- // skip events bubbled up from the children
85
- if (e.target !== e.currentTarget) {
86
- return;
87
- }
88
- // skip if not focused through keyboard
89
- // TODO: handle mouse click focus
90
- const element = e.target;
91
- if (!element.matches(':focus-visible')) {
92
- return;
93
- }
94
- // determine tab direction
95
- // if focused on the same area as current focused area node, it means moving backward
96
- // otherwise, moving forward
97
- const tabDirection = ((_a = this._focusedAreaNode) === null || _a === void 0 ? void 0 : _a.area) === e.target ? 'backward' : 'forward';
98
- const focusedArea = tabDirection === 'forward' ?
99
- (_b = this._focusedAreaNode) === null || _b === void 0 ? void 0 : _b.focusNext() :
100
- (_c = this._focusedAreaNode) === null || _c === void 0 ? void 0 : _c.focusPrevious();
101
- if (focusedArea) {
102
- this._focusedAreaNode = focusedArea;
103
- return;
104
- }
105
- this.focusOutside(tabDirection);
106
- }
107
- onLastGuardFocus(e) {
108
- var _a;
109
- // skip events bubbled up from the children
110
- if (e.target !== e.currentTarget) {
111
- return;
112
- }
113
- // if there is no focused area context, it means focus is moving backwards
114
- // therefore, focus the first tab-able element from the back
115
- if (!this._focusedAreaNode) {
116
- const focusedAreaContext = (_a = this._areaNodes.tail) === null || _a === void 0 ? void 0 : _a.focusPrevious(true);
117
- // set focusedAreaContext if found
118
- if (focusedAreaContext) {
119
- this._focusedAreaNode = focusedAreaContext;
120
- return;
121
- }
122
- // otherwise, focusOutside
123
- this.focusOutside('backward');
124
- return;
125
- }
126
- const focusedArea = this._focusedAreaNode.focusNext();
127
- if (focusedArea) {
128
- this._focusedAreaNode = focusedArea;
129
- }
130
- }
131
- focusOutside(tabDirection) {
132
- // get all focusable elements
133
- const focusableElements = Array.from(document.querySelectorAll(tabbableQuerySelector));
134
- // if forward, focus the element after the last guard element
135
- if (tabDirection === 'forward') {
136
- const lastGuardElementIndex = focusableElements.findIndex(focusableElement => focusableElement === this._lastGuardElement);
137
- const newElementIndex = lastGuardElementIndex + 1;
138
- // focus if within boundary
139
- if (lastGuardElementIndex > 0 && lastGuardElementIndex < focusableElements.length) {
140
- focusableElements[newElementIndex].focus();
141
- }
142
- this._focusedAreaNode = undefined;
143
- return;
144
- }
145
- // otherwise, focus on the element before the root element
146
- const rootElementIndex = focusableElements.findIndex(focusableElement => focusableElement === this._rootElement);
147
- const newElementIndex = rootElementIndex - 1;
148
- // focus if within boundary
149
- if (newElementIndex >= 0 && newElementIndex < focusableElements.length) {
150
- focusableElements[newElementIndex].focus();
151
- }
152
- this._focusedAreaNode = undefined;
153
- return;
154
- }
155
- }
156
- exports.FocusService = FocusService;
157
- const tabbableQuerySelector = funnel_core_1.Browser.Element.tabbable.join(',');
158
- // create AreaNode
159
- class AreaNode {
160
- constructor(area, ordinal) {
161
- this.area = area;
162
- this.ordinal = ordinal;
163
- }
164
- focusNext(inclusive = false) {
165
- // pointer
166
- let current = inclusive ? this : this.next;
167
- // traverse the list forward
168
- while (current) {
169
- const focusAbleElement = current.area.querySelector(tabbableQuerySelector);
170
- // if focus-able element found, focus and return the area node
171
- if (focusAbleElement) {
172
- focusAbleElement.focus();
173
- return current;
174
- }
175
- // otherwise, keep traversing
176
- current = current.next;
177
- }
178
- return undefined;
179
- }
180
- focusPrevious(inclusive = false) {
181
- // pointer
182
- let current = inclusive ? this : this.prev;
183
- // traverse the list backward
184
- while (current) {
185
- const focusAbleElements = Array.from(current.area.querySelectorAll(tabbableQuerySelector));
186
- const focusAbleElement = focusAbleElements.pop();
187
- // if focus-able element found, focus and return the area node
188
- if (focusAbleElement) {
189
- focusAbleElement.focus();
190
- return current;
191
- }
192
- // otherwise, keep traversing
193
- current = current.prev;
194
- }
195
- return undefined;
196
- }
197
- compareTo(that) {
198
- return this.ordinal === that.ordinal
199
- ? 0
200
- : this.ordinal < that.ordinal
201
- ? -1
202
- : 1;
203
- }
204
- }
@@ -1,18 +0,0 @@
1
- import { Transform } from '@nascentdigital/funnel-core';
2
- export declare class SortedLinkedList<T extends SortedLinkedList.Node<T>> {
3
- constructor(list?: SortedLinkedList<T>);
4
- private _head?;
5
- get head(): T | undefined;
6
- private _tail?;
7
- get tail(): T | undefined;
8
- find(matches: Transform<T, boolean>): T | undefined;
9
- insert(node: T): void;
10
- remove(node: T): void;
11
- }
12
- export declare namespace SortedLinkedList {
13
- interface Node<T> {
14
- prev?: Node<T>;
15
- next?: Node<T>;
16
- compareTo(that: Node<T>): number;
17
- }
18
- }