@fluentui/priority-overflow 9.0.2 → 9.1.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.
@@ -1,90 +1,89 @@
1
1
  /**
2
2
  * @param compare - comparison function for items
3
3
  * @returns Priority queue implemented with a min heap
4
- */export function createPriorityQueue(compare) {
5
- const arr = [];
6
- let size = 0;
7
- const left = i => {
8
- return 2 * i + 1;
9
- };
10
- const right = i => {
11
- return 2 * i + 2;
12
- };
13
- const parent = i => {
14
- return Math.floor((i - 1) / 2);
15
- };
16
- const swap = (a, b) => {
17
- const tmp = arr[a];
18
- arr[a] = arr[b];
19
- arr[b] = tmp;
20
- };
21
- const heapify = i => {
22
- let smallest = i;
23
- const l = left(i);
24
- const r = right(i);
25
- if (l < size && compare(arr[l], arr[smallest]) < 0) {
26
- smallest = l;
27
- }
28
- if (r < size && compare(arr[r], arr[smallest]) < 0) {
29
- smallest = r;
30
- }
31
- if (smallest !== i) {
32
- swap(smallest, i);
33
- heapify(smallest);
34
- }
35
- };
36
- const dequeue = () => {
37
- if (size === 0) {
38
- throw new Error('Priority queue empty');
39
- }
40
- const res = arr[0];
41
- arr[0] = arr[--size];
42
- heapify(0);
43
- return res;
44
- };
45
- const peek = () => {
46
- if (size === 0) {
47
- return null;
48
- }
49
- return arr[0];
50
- };
51
- const enqueue = item => {
52
- arr[size++] = item;
53
- let i = size - 1;
54
- let p = parent(i);
55
- while (i > 0 && compare(arr[p], arr[i]) > 0) {
56
- swap(p, i);
57
- i = p;
58
- p = parent(i);
59
- }
60
- };
61
- const contains = item => {
62
- const index = arr.indexOf(item);
63
- return index >= 0 && index < size;
64
- };
65
- const remove = item => {
66
- const i = arr.indexOf(item);
67
- if (i === -1 || i >= size) {
68
- return;
69
- }
70
- arr[i] = arr[--size];
71
- heapify(i);
72
- };
73
- const clear = () => {
74
- size = 0;
75
- };
76
- const all = () => {
77
- return arr.slice(0, size);
78
- };
79
- return {
80
- all,
81
- clear,
82
- contains,
83
- dequeue,
84
- enqueue,
85
- peek,
86
- remove,
87
- size: () => size
88
- };
4
+ */ export function createPriorityQueue(compare) {
5
+ const arr = [];
6
+ let size = 0;
7
+ const left = (i)=>{
8
+ return 2 * i + 1;
9
+ };
10
+ const right = (i)=>{
11
+ return 2 * i + 2;
12
+ };
13
+ const parent = (i)=>{
14
+ return Math.floor((i - 1) / 2);
15
+ };
16
+ const swap = (a, b)=>{
17
+ const tmp = arr[a];
18
+ arr[a] = arr[b];
19
+ arr[b] = tmp;
20
+ };
21
+ const heapify = (i)=>{
22
+ let smallest = i;
23
+ const l = left(i);
24
+ const r = right(i);
25
+ if (l < size && compare(arr[l], arr[smallest]) < 0) {
26
+ smallest = l;
27
+ }
28
+ if (r < size && compare(arr[r], arr[smallest]) < 0) {
29
+ smallest = r;
30
+ }
31
+ if (smallest !== i) {
32
+ swap(smallest, i);
33
+ heapify(smallest);
34
+ }
35
+ };
36
+ const dequeue = ()=>{
37
+ if (size === 0) {
38
+ throw new Error('Priority queue empty');
39
+ }
40
+ const res = arr[0];
41
+ arr[0] = arr[--size];
42
+ heapify(0);
43
+ return res;
44
+ };
45
+ const peek = ()=>{
46
+ if (size === 0) {
47
+ return null;
48
+ }
49
+ return arr[0];
50
+ };
51
+ const enqueue = (item)=>{
52
+ arr[size++] = item;
53
+ let i = size - 1;
54
+ let p = parent(i);
55
+ while(i > 0 && compare(arr[p], arr[i]) > 0){
56
+ swap(p, i);
57
+ i = p;
58
+ p = parent(i);
59
+ }
60
+ };
61
+ const contains = (item)=>{
62
+ const index = arr.indexOf(item);
63
+ return index >= 0 && index < size;
64
+ };
65
+ const remove = (item)=>{
66
+ const i = arr.indexOf(item);
67
+ if (i === -1 || i >= size) {
68
+ return;
69
+ }
70
+ arr[i] = arr[--size];
71
+ heapify(i);
72
+ };
73
+ const clear = ()=>{
74
+ size = 0;
75
+ };
76
+ const all = ()=>{
77
+ return arr.slice(0, size);
78
+ };
79
+ return {
80
+ all,
81
+ clear,
82
+ contains,
83
+ dequeue,
84
+ enqueue,
85
+ peek,
86
+ remove,
87
+ size: ()=>size
88
+ };
89
89
  }
90
- //# sourceMappingURL=priorityQueue.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["createPriorityQueue","compare","arr","size","left","i","right","parent","Math","floor","swap","a","b","tmp","heapify","smallest","l","r","dequeue","Error","res","peek","enqueue","item","p","contains","index","indexOf","remove","clear","all","slice"],"sources":["../src/priorityQueue.ts"],"sourcesContent":["export type PriorityQueueCompareFn<T> = (a: T, b: T) => number;\n\nexport interface PriorityQueue<T> {\n all: () => T[];\n clear: () => void;\n contains: (item: T) => boolean;\n dequeue: () => T;\n enqueue: (item: T) => void;\n peek: () => T | null;\n remove: (item: T) => void;\n size: () => number;\n}\n\n/**\n * @param compare - comparison function for items\n * @returns Priority queue implemented with a min heap\n */\nexport function createPriorityQueue<T>(compare: PriorityQueueCompareFn<T>): PriorityQueue<T> {\n const arr: T[] = [];\n let size = 0;\n\n const left = (i: number) => {\n return 2 * i + 1;\n };\n\n const right = (i: number) => {\n return 2 * i + 2;\n };\n\n const parent = (i: number) => {\n return Math.floor((i - 1) / 2);\n };\n\n const swap = (a: number, b: number) => {\n const tmp = arr[a];\n arr[a] = arr[b];\n arr[b] = tmp;\n };\n\n const heapify = (i: number) => {\n let smallest = i;\n const l = left(i);\n const r = right(i);\n\n if (l < size && compare(arr[l], arr[smallest]) < 0) {\n smallest = l;\n }\n\n if (r < size && compare(arr[r], arr[smallest]) < 0) {\n smallest = r;\n }\n\n if (smallest !== i) {\n swap(smallest, i);\n heapify(smallest);\n }\n };\n\n const dequeue = () => {\n if (size === 0) {\n throw new Error('Priority queue empty');\n }\n\n const res = arr[0];\n arr[0] = arr[--size];\n heapify(0);\n\n return res;\n };\n\n const peek = () => {\n if (size === 0) {\n return null;\n }\n\n return arr[0];\n };\n\n const enqueue = (item: T) => {\n arr[size++] = item;\n let i = size - 1;\n let p = parent(i);\n while (i > 0 && compare(arr[p], arr[i]) > 0) {\n swap(p, i);\n i = p;\n p = parent(i);\n }\n };\n\n const contains = (item: T) => {\n const index = arr.indexOf(item);\n return index >= 0 && index < size;\n };\n\n const remove = (item: T) => {\n const i = arr.indexOf(item);\n\n if (i === -1 || i >= size) {\n return;\n }\n\n arr[i] = arr[--size];\n heapify(i);\n };\n\n const clear = () => {\n size = 0;\n };\n\n const all = () => {\n return arr.slice(0, size);\n };\n\n return {\n all,\n clear,\n contains,\n dequeue,\n enqueue,\n peek,\n remove,\n size: () => size,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"sources":["priorityQueue.ts"],"sourcesContent":["export type PriorityQueueCompareFn<T> = (a: T, b: T) => number;\n\nexport interface PriorityQueue<T> {\n all: () => T[];\n clear: () => void;\n contains: (item: T) => boolean;\n dequeue: () => T;\n enqueue: (item: T) => void;\n peek: () => T | null;\n remove: (item: T) => void;\n size: () => number;\n}\n\n/**\n * @param compare - comparison function for items\n * @returns Priority queue implemented with a min heap\n */\nexport function createPriorityQueue<T>(compare: PriorityQueueCompareFn<T>): PriorityQueue<T> {\n const arr: T[] = [];\n let size = 0;\n\n const left = (i: number) => {\n return 2 * i + 1;\n };\n\n const right = (i: number) => {\n return 2 * i + 2;\n };\n\n const parent = (i: number) => {\n return Math.floor((i - 1) / 2);\n };\n\n const swap = (a: number, b: number) => {\n const tmp = arr[a];\n arr[a] = arr[b];\n arr[b] = tmp;\n };\n\n const heapify = (i: number) => {\n let smallest = i;\n const l = left(i);\n const r = right(i);\n\n if (l < size && compare(arr[l], arr[smallest]) < 0) {\n smallest = l;\n }\n\n if (r < size && compare(arr[r], arr[smallest]) < 0) {\n smallest = r;\n }\n\n if (smallest !== i) {\n swap(smallest, i);\n heapify(smallest);\n }\n };\n\n const dequeue = () => {\n if (size === 0) {\n throw new Error('Priority queue empty');\n }\n\n const res = arr[0];\n arr[0] = arr[--size];\n heapify(0);\n\n return res;\n };\n\n const peek = () => {\n if (size === 0) {\n return null;\n }\n\n return arr[0];\n };\n\n const enqueue = (item: T) => {\n arr[size++] = item;\n let i = size - 1;\n let p = parent(i);\n while (i > 0 && compare(arr[p], arr[i]) > 0) {\n swap(p, i);\n i = p;\n p = parent(i);\n }\n };\n\n const contains = (item: T) => {\n const index = arr.indexOf(item);\n return index >= 0 && index < size;\n };\n\n const remove = (item: T) => {\n const i = arr.indexOf(item);\n\n if (i === -1 || i >= size) {\n return;\n }\n\n arr[i] = arr[--size];\n heapify(i);\n };\n\n const clear = () => {\n size = 0;\n };\n\n const all = () => {\n return arr.slice(0, size);\n };\n\n return {\n all,\n clear,\n contains,\n dequeue,\n enqueue,\n peek,\n remove,\n size: () => size,\n };\n}\n"],"names":["createPriorityQueue","compare","arr","size","left","i","right","parent","Math","floor","swap","a","b","tmp","heapify","smallest","l","r","dequeue","Error","res","peek","enqueue","item","p","contains","index","indexOf","remove","clear","all","slice"],"mappings":"AAaA;;;CAGC,GACD,OAAO,SAASA,oBAAuBC,OAAkC,EAAoB;IAC3F,MAAMC,MAAW,EAAE;IACnB,IAAIC,OAAO;IAEX,MAAMC,OAAO,CAACC,IAAc;QAC1B,OAAO,IAAIA,IAAI;IACjB;IAEA,MAAMC,QAAQ,CAACD,IAAc;QAC3B,OAAO,IAAIA,IAAI;IACjB;IAEA,MAAME,SAAS,CAACF,IAAc;QAC5B,OAAOG,KAAKC,KAAK,CAAC,AAACJ,CAAAA,IAAI,CAAA,IAAK;IAC9B;IAEA,MAAMK,OAAO,CAACC,GAAWC,IAAc;QACrC,MAAMC,MAAMX,GAAG,CAACS,EAAE;QAClBT,GAAG,CAACS,EAAE,GAAGT,GAAG,CAACU,EAAE;QACfV,GAAG,CAACU,EAAE,GAAGC;IACX;IAEA,MAAMC,UAAU,CAACT,IAAc;QAC7B,IAAIU,WAAWV;QACf,MAAMW,IAAIZ,KAAKC;QACf,MAAMY,IAAIX,MAAMD;QAEhB,IAAIW,IAAIb,QAAQF,QAAQC,GAAG,CAACc,EAAE,EAAEd,GAAG,CAACa,SAAS,IAAI,GAAG;YAClDA,WAAWC;QACb,CAAC;QAED,IAAIC,IAAId,QAAQF,QAAQC,GAAG,CAACe,EAAE,EAAEf,GAAG,CAACa,SAAS,IAAI,GAAG;YAClDA,WAAWE;QACb,CAAC;QAED,IAAIF,aAAaV,GAAG;YAClBK,KAAKK,UAAUV;YACfS,QAAQC;QACV,CAAC;IACH;IAEA,MAAMG,UAAU,IAAM;QACpB,IAAIf,SAAS,GAAG;YACd,MAAM,IAAIgB,MAAM,wBAAwB;QAC1C,CAAC;QAED,MAAMC,MAAMlB,GAAG,CAAC,EAAE;QAClBA,GAAG,CAAC,EAAE,GAAGA,GAAG,CAAC,EAAEC,KAAK;QACpBW,QAAQ;QAER,OAAOM;IACT;IAEA,MAAMC,OAAO,IAAM;QACjB,IAAIlB,SAAS,GAAG;YACd,OAAO,IAAI;QACb,CAAC;QAED,OAAOD,GAAG,CAAC,EAAE;IACf;IAEA,MAAMoB,UAAU,CAACC,OAAY;QAC3BrB,GAAG,CAACC,OAAO,GAAGoB;QACd,IAAIlB,IAAIF,OAAO;QACf,IAAIqB,IAAIjB,OAAOF;QACf,MAAOA,IAAI,KAAKJ,QAAQC,GAAG,CAACsB,EAAE,EAAEtB,GAAG,CAACG,EAAE,IAAI,EAAG;YAC3CK,KAAKc,GAAGnB;YACRA,IAAImB;YACJA,IAAIjB,OAAOF;QACb;IACF;IAEA,MAAMoB,WAAW,CAACF,OAAY;QAC5B,MAAMG,QAAQxB,IAAIyB,OAAO,CAACJ;QAC1B,OAAOG,SAAS,KAAKA,QAAQvB;IAC/B;IAEA,MAAMyB,SAAS,CAACL,OAAY;QAC1B,MAAMlB,IAAIH,IAAIyB,OAAO,CAACJ;QAEtB,IAAIlB,MAAM,CAAC,KAAKA,KAAKF,MAAM;YACzB;QACF,CAAC;QAEDD,GAAG,CAACG,EAAE,GAAGH,GAAG,CAAC,EAAEC,KAAK;QACpBW,QAAQT;IACV;IAEA,MAAMwB,QAAQ,IAAM;QAClB1B,OAAO;IACT;IAEA,MAAM2B,MAAM,IAAM;QAChB,OAAO5B,IAAI6B,KAAK,CAAC,GAAG5B;IACtB;IAEA,OAAO;QACL2B;QACAD;QACAJ;QACAP;QACAI;QACAD;QACAO;QACAzB,MAAM,IAAMA;IACd;AACF,CAAC"}
package/lib/types.js CHANGED
@@ -1,2 +1 @@
1
- export {};
2
- //# sourceMappingURL=types.js.map
1
+ export { };
package/lib/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["../src/types.ts"],"sourcesContent":["export type OverflowDirection = 'start' | 'end';\nexport type OverflowAxis = 'horizontal' | 'vertical';\nexport type OverflowGroupState = 'visible' | 'hidden' | 'overflow';\nexport interface OverflowItemEntry {\n /**\n * HTML element that will be disappear when overflowed\n */\n element: HTMLElement;\n /**\n * Lower priority items are invisible first when the container is overflowed\n * @default 0\n */\n priority: number;\n /**\n * Specific id, used to track visibility and provide updates to consumers\n */\n id: string;\n\n groupId?: string;\n}\n\n/**\n * signature similar to standard event listeners, but typed to handle the custom event\n */\nexport type OnUpdateOverflow = (data: OverflowEventPayload) => void;\n\nexport type OnUpdateItemVisibility = (data: OnUpdateItemVisibilityPayload) => void;\n\n/**\n * Payload of the custom DOM event for overflow updates\n */\nexport interface OverflowEventPayload {\n visibleItems: OverflowItemEntry[];\n invisibleItems: OverflowItemEntry[];\n groupVisibility: Record<string, OverflowGroupState>;\n}\n\nexport interface OnUpdateItemVisibilityPayload {\n item: OverflowItemEntry;\n visible: boolean;\n}\n\nexport interface ObserveOptions {\n /**\n * Padding (in px) at the end of the container before overflow occurs\n * Useful to account for extra elements (i.e. dropdown menu)\n * or to account for any kinds of margins between items which are hard to measure with JS\n * @default 10\n */\n padding?: number;\n /**\n * Direction where items are removed when overflow occurs\n * @default end\n */\n overflowDirection?: OverflowDirection;\n\n /**\n * Horizontal or vertical overflow\n * @default horizontal\n */\n overflowAxis?: OverflowAxis;\n\n /**\n * The minimum number of visible items\n */\n minimumVisible?: number;\n\n /**\n * Callback when item visibility is updated\n */\n onUpdateItemVisibility: OnUpdateItemVisibility;\n\n /**\n * Callback when item visibility is updated\n */\n onUpdateOverflow: OnUpdateOverflow;\n}\n\n/**\n * @internal\n */\nexport interface OverflowManager {\n /**\n * Starts observing the container and managing the overflow state\n */\n observe: (container: HTMLElement, options: ObserveOptions) => void;\n /**\n * Stops observing the container\n */\n disconnect: () => void;\n /**\n * Add overflow items\n */\n addItem: (items: OverflowItemEntry) => void;\n /**\n * Remove overflow item\n */\n removeItem: (itemId: string) => void;\n /**\n * Manually update the overflow, updates are batched and async\n */\n update: () => void;\n /**\n * Manually update the overflow sync\n */\n forceUpdate: () => void;\n\n /**\n * Adds an element that opens an overflow menu. This is used to calculate\n * available space and check if additional items need to overflow\n */\n addOverflowMenu: (element: HTMLElement) => void;\n\n /**\n * Unsets the overflow menu element\n */\n removeOverflowMenu: () => void;\n}\n"],"mappings":"AAAA"}
1
+ {"version":3,"sources":["types.ts"],"sourcesContent":["export type OverflowDirection = 'start' | 'end';\nexport type OverflowAxis = 'horizontal' | 'vertical';\nexport type OverflowGroupState = 'visible' | 'hidden' | 'overflow';\nexport interface OverflowItemEntry {\n /**\n * HTML element that will be disappear when overflowed\n */\n element: HTMLElement;\n /**\n * Lower priority items are invisible first when the container is overflowed\n * @default 0\n */\n priority: number;\n /**\n * Specific id, used to track visibility and provide updates to consumers\n */\n id: string;\n\n groupId?: string;\n}\n\nexport interface OverflowDividerEntry {\n /**\n * HTML element that will be disappear when overflowed\n */\n element: HTMLElement;\n\n groupId: string;\n}\n\n/**\n * signature similar to standard event listeners, but typed to handle the custom event\n */\nexport type OnUpdateOverflow = (data: OverflowEventPayload) => void;\n\nexport type OnUpdateItemVisibility = (data: OnUpdateItemVisibilityPayload) => void;\n\n/**\n * Payload of the custom DOM event for overflow updates\n */\nexport interface OverflowEventPayload {\n visibleItems: OverflowItemEntry[];\n invisibleItems: OverflowItemEntry[];\n groupVisibility: Record<string, OverflowGroupState>;\n}\n\nexport interface OnUpdateItemVisibilityPayload {\n item: OverflowItemEntry;\n visible: boolean;\n}\n\nexport interface ObserveOptions {\n /**\n * Padding (in px) at the end of the container before overflow occurs\n * Useful to account for extra elements (i.e. dropdown menu)\n * or to account for any kinds of margins between items which are hard to measure with JS\n * @default 10\n */\n padding?: number;\n /**\n * Direction where items are removed when overflow occurs\n * @default end\n */\n overflowDirection?: OverflowDirection;\n\n /**\n * Horizontal or vertical overflow\n * @default horizontal\n */\n overflowAxis?: OverflowAxis;\n\n /**\n * The minimum number of visible items\n */\n minimumVisible?: number;\n\n /**\n * Callback when item visibility is updated\n */\n onUpdateItemVisibility: OnUpdateItemVisibility;\n\n /**\n * Callback when item visibility is updated\n */\n onUpdateOverflow: OnUpdateOverflow;\n}\n\n/**\n * @internal\n */\nexport interface OverflowManager {\n /**\n * Starts observing the container and managing the overflow state\n */\n observe: (container: HTMLElement, options: ObserveOptions) => void;\n /**\n * Stops observing the container\n */\n disconnect: () => void;\n /**\n * Add overflow items\n */\n addItem: (items: OverflowItemEntry) => void;\n /**\n * Remove overflow item\n */\n removeItem: (itemId: string) => void;\n /**\n * Manually update the overflow, updates are batched and async\n */\n update: () => void;\n /**\n * Manually update the overflow sync\n */\n forceUpdate: () => void;\n\n /**\n * Adds an element that opens an overflow menu. This is used to calculate\n * available space and check if additional items need to overflow\n */\n addOverflowMenu: (element: HTMLElement) => void;\n\n /**\n * Add overflow divider\n */\n addDivider: (divider: OverflowDividerEntry) => void;\n\n /**\n * Remove overflow divider\n */\n removeDivider: (groupId: string) => void;\n\n /**\n * Unsets the overflow menu element\n */\n removeOverflowMenu: () => void;\n}\n"],"names":[],"mappings":"AAAA,WAwIC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ DATA_OVERFLOWING: ()=>DATA_OVERFLOWING,
13
+ DATA_OVERFLOW_GROUP: ()=>DATA_OVERFLOW_GROUP
14
+ });
15
+ const DATA_OVERFLOWING = 'data-overflowing';
16
+ const DATA_OVERFLOW_GROUP = 'data-overflow-group';
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["consts.js"],"sourcesContent":["export const DATA_OVERFLOWING = 'data-overflowing';\nexport const DATA_OVERFLOW_GROUP = 'data-overflow-group';\n"],"names":["DATA_OVERFLOWING","DATA_OVERFLOW_GROUP"],"mappings":";;;;;;;;;;;IAAaA,gBAAgB,MAAhBA;IACAC,mBAAmB,MAAnBA;;AADN,MAAMD,mBAAmB;AACzB,MAAMC,sBAAsB"}
@@ -24,6 +24,4 @@ function debounce(fn) {
24
24
  });
25
25
  }
26
26
  };
27
- } //# sourceMappingURL=debounce.js.map
28
-
29
- //# sourceMappingURL=debounce.js.map
27
+ }
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/debounce.js"],"sourcesContent":["/**\n * Microtask debouncer\n * https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide\n * @param fn - Function to debounce\n * @returns debounced function\n */export function debounce(fn) {\n let pending;\n return () => {\n if (!pending) {\n pending = true;\n queueMicrotask(() => {\n // Need to set pending to `false` before the debounced function is run.\n // React can actually interrupt the function while it's running!\n pending = false;\n fn();\n });\n }\n };\n}\n//# sourceMappingURL=debounce.js.map"],"names":["debounce","fn","pending","queueMicrotask"],"mappings":"AAAA;;;;;CAKC;;;;+BAAkBA;;aAAAA;;AAAT,SAASA,SAASC,EAAE,EAAE;IAC9B,IAAIC;IACJ,OAAO,IAAM;QACX,IAAI,CAACA,SAAS;YACZA,UAAU,IAAI;YACdC,eAAe,IAAM;gBACnB,uEAAuE;gBACvE,gEAAgE;gBAChED,UAAU,KAAK;gBACfD;YACF;QACF,CAAC;IACH;AACF,EACA,oCAAoC"}
1
+ {"version":3,"sources":["debounce.js"],"sourcesContent":["/**\n * Microtask debouncer\n * https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide\n * @param fn - Function to debounce\n * @returns debounced function\n */ export function debounce(fn) {\n let pending;\n return ()=>{\n if (!pending) {\n pending = true;\n queueMicrotask(()=>{\n // Need to set pending to `false` before the debounced function is run.\n // React can actually interrupt the function while it's running!\n pending = false;\n fn();\n });\n }\n };\n}\n"],"names":["debounce","fn","pending","queueMicrotask"],"mappings":"AAAA;;;;;CAKC;;;;+BAAmBA;;aAAAA;;AAAT,SAASA,SAASC,EAAE,EAAE;IAC7B,IAAIC;IACJ,OAAO,IAAI;QACP,IAAI,CAACA,SAAS;YACVA,UAAU,IAAI;YACdC,eAAe,IAAI;gBACf,uEAAuE;gBACvE,gEAAgE;gBAChED,UAAU,KAAK;gBACfD;YACJ;QACJ,CAAC;IACL;AACJ"}
@@ -7,6 +7,3 @@ Object.defineProperty(exports, "createOverflowManager", {
7
7
  get: ()=>_overflowManager.createOverflowManager
8
8
  });
9
9
  const _overflowManager = require("./overflowManager");
10
- //# sourceMappingURL=index.js.map
11
-
12
- //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/index.js"],"sourcesContent":["export { createOverflowManager } from './overflowManager';\n//# sourceMappingURL=index.js.map"],"names":["createOverflowManager"],"mappings":";;;;+BAASA;;aAAAA,sCAAqB;;iCAAQ;CACtC,iCAAiC"}
1
+ {"version":3,"sources":["index.js"],"sourcesContent":["export { createOverflowManager } from './overflowManager';\n"],"names":["createOverflowManager"],"mappings":";;;;+BAASA;;aAAAA,sCAAqB;;iCAAQ"}
@@ -6,15 +6,18 @@ Object.defineProperty(exports, "createOverflowManager", {
6
6
  enumerable: true,
7
7
  get: ()=>createOverflowManager
8
8
  });
9
+ const _consts = require("./consts");
9
10
  const _debounce = require("./debounce");
10
11
  const _priorityQueue = require("./priorityQueue");
12
+ var _groups, _groupId;
11
13
  function createOverflowManager() {
12
14
  let container;
13
15
  let overflowMenu;
14
16
  // Set as true when resize observer is observing
15
17
  let observing = false;
16
18
  // If true, next update will dispatch to onUpdateOverflow even if queue top states don't change
17
- let forceDispatch = false;
19
+ // Initially true to force dispatch on first mount
20
+ let forceDispatch = true;
18
21
  const options = {
19
22
  padding: 10,
20
23
  overflowAxis: 'horizontal',
@@ -24,13 +27,66 @@ function createOverflowManager() {
24
27
  onUpdateOverflow: ()=>undefined
25
28
  };
26
29
  const overflowItems = {};
27
- const overflowGroups = {};
30
+ const overflowDividers = {};
28
31
  const resizeObserver = new ResizeObserver((entries)=>{
29
32
  if (!entries[0] || !container) {
30
33
  return;
31
34
  }
32
35
  update();
33
36
  });
37
+ const getNextItem = (queueToDequeue, queueToEnqueue)=>{
38
+ const nextItem = queueToDequeue.dequeue();
39
+ queueToEnqueue.enqueue(nextItem);
40
+ return overflowItems[nextItem];
41
+ };
42
+ const createGroupManager = ()=>{
43
+ const groupVisibility = {};
44
+ const groups = {};
45
+ function updateGroupVisibility(groupId) {
46
+ const group = groups[groupId];
47
+ if (group.invisibleItemIds.size && group.visibleItemIds.size) {
48
+ groupVisibility[groupId] = 'overflow';
49
+ } else if (group.visibleItemIds.size === 0) {
50
+ groupVisibility[groupId] = 'hidden';
51
+ } else {
52
+ groupVisibility[groupId] = 'visible';
53
+ }
54
+ }
55
+ function isGroupVisible(groupId) {
56
+ return groupVisibility[groupId] === 'visible' || groupVisibility[groupId] === 'overflow';
57
+ }
58
+ return {
59
+ groupVisibility: ()=>groupVisibility,
60
+ isSingleItemVisible (itemId, groupId) {
61
+ return isGroupVisible(groupId) && groups[groupId].visibleItemIds.has(itemId) && groups[groupId].visibleItemIds.size === 1;
62
+ },
63
+ addItem (itemId, groupId) {
64
+ var _;
65
+ (_ = (_groups = groups)[_groupId = groupId]) !== null && _ !== void 0 ? _ : _groups[_groupId] = {
66
+ visibleItemIds: new Set(),
67
+ invisibleItemIds: new Set()
68
+ };
69
+ groups[groupId].visibleItemIds.add(itemId);
70
+ updateGroupVisibility(groupId);
71
+ },
72
+ removeItem (itemId, groupId) {
73
+ groups[groupId].invisibleItemIds.delete(itemId);
74
+ groups[groupId].visibleItemIds.delete(itemId);
75
+ updateGroupVisibility(groupId);
76
+ },
77
+ showItem (itemId, groupId) {
78
+ groups[groupId].invisibleItemIds.delete(itemId);
79
+ groups[groupId].visibleItemIds.add(itemId);
80
+ updateGroupVisibility(groupId);
81
+ },
82
+ hideItem (itemId, groupId) {
83
+ groups[groupId].invisibleItemIds.add(itemId);
84
+ groups[groupId].visibleItemIds.delete(itemId);
85
+ updateGroupVisibility(groupId);
86
+ }
87
+ };
88
+ };
89
+ const groupManager = createGroupManager();
34
90
  const invisibleItemQueue = (0, _priorityQueue.createPriorityQueue)((a, b)=>{
35
91
  const itemA = overflowItems[a];
36
92
  const itemB = overflowItems[b];
@@ -60,32 +116,38 @@ function createOverflowManager() {
60
116
  const getOffsetSize = (el)=>{
61
117
  return options.overflowAxis === 'horizontal' ? el.offsetWidth : el.offsetHeight;
62
118
  };
63
- const makeItemVisible = ()=>{
64
- const nextVisible = invisibleItemQueue.dequeue();
65
- visibleItemQueue.enqueue(nextVisible);
66
- const item = overflowItems[nextVisible];
119
+ function computeSizeChange(entry) {
120
+ const dividerWidth = entry.groupId && groupManager.isSingleItemVisible(entry.id, entry.groupId) && overflowDividers[entry.groupId] ? getOffsetSize(overflowDividers[entry.groupId].element) : 0;
121
+ return getOffsetSize(entry.element) + dividerWidth;
122
+ }
123
+ const showItem = ()=>{
124
+ const item = getNextItem(invisibleItemQueue, visibleItemQueue);
67
125
  options.onUpdateItemVisibility({
68
126
  item,
69
127
  visible: true
70
128
  });
71
129
  if (item.groupId) {
72
- overflowGroups[item.groupId].invisibleItemIds.delete(item.id);
73
- overflowGroups[item.groupId].visibleItemIds.add(item.id);
130
+ groupManager.showItem(item.id, item.groupId);
131
+ if (groupManager.isSingleItemVisible(item.id, item.groupId)) {
132
+ var _overflowDividers_item_groupId;
133
+ (_overflowDividers_item_groupId = overflowDividers[item.groupId]) === null || _overflowDividers_item_groupId === void 0 ? void 0 : _overflowDividers_item_groupId.element.removeAttribute(_consts.DATA_OVERFLOWING);
134
+ }
74
135
  }
75
- return getOffsetSize(item.element);
136
+ return computeSizeChange(item);
76
137
  };
77
- const makeItemInvisible = ()=>{
78
- const nextInvisible = visibleItemQueue.dequeue();
79
- invisibleItemQueue.enqueue(nextInvisible);
80
- const item = overflowItems[nextInvisible];
81
- const width = getOffsetSize(item.element);
138
+ const hideItem = ()=>{
139
+ const item = getNextItem(visibleItemQueue, invisibleItemQueue);
140
+ const width = computeSizeChange(item);
82
141
  options.onUpdateItemVisibility({
83
142
  item,
84
143
  visible: false
85
144
  });
86
145
  if (item.groupId) {
87
- overflowGroups[item.groupId].visibleItemIds.delete(item.id);
88
- overflowGroups[item.groupId].invisibleItemIds.add(item.id);
146
+ if (groupManager.isSingleItemVisible(item.id, item.groupId)) {
147
+ var _overflowDividers_item_groupId;
148
+ (_overflowDividers_item_groupId = overflowDividers[item.groupId]) === null || _overflowDividers_item_groupId === void 0 ? void 0 : _overflowDividers_item_groupId.element.setAttribute(_consts.DATA_OVERFLOWING, '');
149
+ }
150
+ groupManager.hideItem(item.id, item.groupId);
89
151
  }
90
152
  return width;
91
153
  };
@@ -94,56 +156,32 @@ function createOverflowManager() {
94
156
  const invisibleItemIds = invisibleItemQueue.all();
95
157
  const visibleItems = visibleItemIds.map((itemId)=>overflowItems[itemId]);
96
158
  const invisibleItems = invisibleItemIds.map((itemId)=>overflowItems[itemId]);
97
- const groupVisibility = {};
98
- Object.entries(overflowGroups).forEach(([groupId, groupState])=>{
99
- if (groupState.invisibleItemIds.size && groupState.visibleItemIds.size) {
100
- groupVisibility[groupId] = 'overflow';
101
- } else if (groupState.visibleItemIds.size === 0) {
102
- groupVisibility[groupId] = 'hidden';
103
- } else {
104
- groupVisibility[groupId] = 'visible';
105
- }
106
- });
107
159
  options.onUpdateOverflow({
108
160
  visibleItems,
109
161
  invisibleItems,
110
- groupVisibility
162
+ groupVisibility: groupManager.groupVisibility()
111
163
  });
112
164
  };
113
165
  const processOverflowItems = ()=>{
114
166
  if (!container) {
115
167
  return false;
116
168
  }
117
- const availableSize = getOffsetSize(container) - options.padding;
118
- const overflowMenuOffset = overflowMenu ? getOffsetSize(overflowMenu) : 0;
169
+ const totalDividersWidth = Object.values(overflowDividers).map((dvdr)=>dvdr.groupId ? getOffsetSize(dvdr.element) : 0).reduce((prev, current)=>prev + current, 0);
170
+ const availableSize = getOffsetSize(container) - options.padding - totalDividersWidth - (overflowMenu ? getOffsetSize(overflowMenu) : 0);
119
171
  // Snapshot of the visible/invisible state to compare for updates
120
172
  const visibleTop = visibleItemQueue.peek();
121
173
  const invisibleTop = invisibleItemQueue.peek();
122
- const visibleItemIds = visibleItemQueue.all();
123
- let currentWidth = visibleItemIds.reduce((sum, visibleItemId)=>{
124
- const child = overflowItems[visibleItemId].element;
125
- return sum + getOffsetSize(child);
126
- }, 0);
174
+ let currentWidth = visibleItemQueue.all().map((id)=>overflowItems[id].element).map(getOffsetSize).reduce((prev, current)=>prev + current, 0);
127
175
  // Add items until available width is filled - can result in overflow
128
176
  while(currentWidth < availableSize && invisibleItemQueue.size() > 0){
129
- currentWidth += makeItemVisible();
177
+ currentWidth += showItem();
130
178
  }
131
179
  // Remove items until there's no more overflow
132
- while(currentWidth > availableSize && visibleItemQueue.size() > 0){
133
- if (visibleItemQueue.size() <= options.minimumVisible) {
134
- break;
135
- }
136
- currentWidth -= makeItemInvisible();
137
- }
138
- // make sure the overflow menu can fit
139
- if (visibleItemQueue.size() > options.minimumVisible && invisibleItemQueue.size() > 0 && currentWidth + overflowMenuOffset > availableSize) {
140
- makeItemInvisible();
180
+ while(currentWidth > availableSize && visibleItemQueue.size() > options.minimumVisible){
181
+ currentWidth -= hideItem();
141
182
  }
142
183
  // only update when the state of visible/invisible items has changed
143
- if (visibleItemQueue.peek() !== visibleTop || invisibleItemQueue.peek() !== invisibleTop) {
144
- return true;
145
- }
146
- return false;
184
+ return visibleItemQueue.peek() !== visibleTop || invisibleItemQueue.peek() !== invisibleTop;
147
185
  };
148
186
  const forceUpdate = ()=>{
149
187
  if (processOverflowItems() || forceDispatch) {
@@ -177,22 +215,34 @@ function createOverflowManager() {
177
215
  visibleItemQueue.enqueue(item.id);
178
216
  }
179
217
  if (item.groupId) {
180
- if (!overflowGroups[item.groupId]) {
181
- overflowGroups[item.groupId] = {
182
- visibleItemIds: new Set(),
183
- invisibleItemIds: new Set()
184
- };
185
- }
186
- overflowGroups[item.groupId].visibleItemIds.add(item.id);
218
+ groupManager.addItem(item.id, item.groupId);
219
+ item.element.setAttribute(_consts.DATA_OVERFLOW_GROUP, item.groupId);
187
220
  }
188
221
  update();
189
222
  };
190
223
  const addOverflowMenu = (el)=>{
191
224
  overflowMenu = el;
192
225
  };
226
+ const addDivider = (divider)=>{
227
+ if (!divider.groupId || overflowDividers[divider.groupId]) {
228
+ return;
229
+ }
230
+ divider.element.setAttribute(_consts.DATA_OVERFLOW_GROUP, divider.groupId);
231
+ overflowDividers[divider.groupId] = divider;
232
+ };
193
233
  const removeOverflowMenu = ()=>{
194
234
  overflowMenu = undefined;
195
235
  };
236
+ const removeDivider = (groupId)=>{
237
+ if (!overflowDividers[groupId]) {
238
+ return;
239
+ }
240
+ const divider = overflowDividers[groupId];
241
+ if (divider.groupId) {
242
+ delete overflowDividers[groupId];
243
+ divider.element.removeAttribute(_consts.DATA_OVERFLOW_GROUP);
244
+ }
245
+ };
196
246
  const removeItem = (itemId)=>{
197
247
  if (!overflowItems[itemId]) {
198
248
  return;
@@ -201,8 +251,8 @@ function createOverflowManager() {
201
251
  visibleItemQueue.remove(itemId);
202
252
  invisibleItemQueue.remove(itemId);
203
253
  if (item.groupId) {
204
- overflowGroups[item.groupId].visibleItemIds.delete(item.id);
205
- overflowGroups[item.groupId].invisibleItemIds.delete(item.id);
254
+ groupManager.removeItem(item.id, item.groupId);
255
+ item.element.removeAttribute(_consts.DATA_OVERFLOW_GROUP);
206
256
  }
207
257
  delete overflowItems[itemId];
208
258
  update();
@@ -215,8 +265,8 @@ function createOverflowManager() {
215
265
  removeItem,
216
266
  update,
217
267
  addOverflowMenu,
218
- removeOverflowMenu
268
+ removeOverflowMenu,
269
+ addDivider,
270
+ removeDivider
219
271
  };
220
- } //# sourceMappingURL=overflowManager.js.map
221
-
222
- //# sourceMappingURL=overflowManager.js.map
272
+ }