@douyinfe/semi-foundation 2.70.1 → 2.71.0-alpha.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 (58) hide show
  1. package/cascader/constants.ts +2 -0
  2. package/cascader/foundation.ts +49 -2
  3. package/dragMove/foundation.ts +194 -0
  4. package/highlight/foundation.ts +211 -0
  5. package/jsonViewer/constants.ts +7 -0
  6. package/jsonViewer/foundation.ts +72 -0
  7. package/jsonViewer/jsonViewer.scss +200 -0
  8. package/jsonViewer/script/build.js +51 -0
  9. package/jsonViewer/variables.scss +15 -0
  10. package/lib/cjs/cascader/constants.d.ts +2 -0
  11. package/lib/cjs/cascader/constants.js +3 -1
  12. package/lib/cjs/cascader/foundation.d.ts +3 -0
  13. package/lib/cjs/cascader/foundation.js +55 -3
  14. package/lib/cjs/dragMove/foundation.d.ts +45 -0
  15. package/lib/cjs/dragMove/foundation.js +162 -0
  16. package/lib/cjs/highlight/foundation.d.ts +84 -0
  17. package/lib/cjs/highlight/foundation.js +184 -0
  18. package/lib/cjs/jsonViewer/constants.d.ts +4 -0
  19. package/lib/cjs/jsonViewer/constants.js +10 -0
  20. package/lib/cjs/jsonViewer/foundation.d.ts +24 -0
  21. package/lib/cjs/jsonViewer/foundation.js +69 -0
  22. package/lib/cjs/jsonViewer/jsonViewer.css +168 -0
  23. package/lib/cjs/jsonViewer/jsonViewer.scss +200 -0
  24. package/lib/cjs/jsonViewer/variables.scss +15 -0
  25. package/lib/cjs/lottie/foundation.d.ts +1 -1
  26. package/lib/cjs/resizable/foundation.d.ts +6 -2
  27. package/lib/cjs/tree/tree.css +1 -0
  28. package/lib/cjs/tree/tree.scss +2 -0
  29. package/lib/es/cascader/constants.d.ts +2 -0
  30. package/lib/es/cascader/constants.js +3 -1
  31. package/lib/es/cascader/foundation.d.ts +3 -0
  32. package/lib/es/cascader/foundation.js +55 -3
  33. package/lib/es/dragMove/foundation.d.ts +45 -0
  34. package/lib/es/dragMove/foundation.js +153 -0
  35. package/lib/es/highlight/foundation.d.ts +84 -0
  36. package/lib/es/highlight/foundation.js +174 -0
  37. package/lib/es/jsonViewer/constants.d.ts +4 -0
  38. package/lib/es/jsonViewer/constants.js +5 -0
  39. package/lib/es/jsonViewer/foundation.d.ts +24 -0
  40. package/lib/es/jsonViewer/foundation.js +62 -0
  41. package/lib/es/jsonViewer/jsonViewer.css +168 -0
  42. package/lib/es/jsonViewer/jsonViewer.scss +200 -0
  43. package/lib/es/jsonViewer/variables.scss +15 -0
  44. package/lib/es/lottie/foundation.d.ts +1 -1
  45. package/lib/es/resizable/foundation.d.ts +6 -2
  46. package/lib/es/resizable/foundation.js +3 -2
  47. package/lib/es/tree/tree.css +1 -0
  48. package/lib/es/tree/tree.scss +2 -0
  49. package/lottie/foundation.ts +2 -2
  50. package/package.json +5 -3
  51. package/resizable/foundation.ts +19 -5
  52. package/tree/tree.scss +2 -0
  53. package/tsconfig.json +1 -1
  54. package/lib/cjs/utils/getHighlight.d.ts +0 -45
  55. package/lib/cjs/utils/getHighlight.js +0 -175
  56. package/lib/es/utils/getHighlight.d.ts +0 -45
  57. package/lib/es/utils/getHighlight.js +0 -166
  58. package/utils/getHighlight.ts +0 -178
@@ -107,6 +107,7 @@
107
107
  .semi-tree-option-list .semi-tree-option-highlight {
108
108
  font-weight: 600;
109
109
  color: var(--semi-color-primary);
110
+ background-color: inherit;
110
111
  }
111
112
  .semi-tree-option-list .semi-tree-option-hidden {
112
113
  display: none;
@@ -137,6 +137,8 @@ $module: #{$prefix}-tree;
137
137
  &-highlight {
138
138
  font-weight: $font-tree_option_hightlight-fontWeight;
139
139
  color: $color-tree_option_hightlight-text;
140
+ // set inherit to override highlight component default bgc
141
+ background-color: inherit;
140
142
  }
141
143
 
142
144
  &-hidden {
@@ -14,6 +14,8 @@ declare const strings: {
14
14
  readonly NONE_MERGE_TYPE: "none";
15
15
  readonly SEARCH_POSITION_TRIGGER: "trigger";
16
16
  readonly SEARCH_POSITION_CUSTOM: "custom";
17
+ readonly RELATED: "related";
18
+ readonly UN_RELATED: "unRelated";
17
19
  };
18
20
  declare const numbers: {};
19
21
  export { cssClasses, strings, numbers };
@@ -15,7 +15,9 @@ const strings = {
15
15
  AUTO_MERGE_VALUE_MERGE_TYPE: 'autoMergeValue',
16
16
  NONE_MERGE_TYPE: 'none',
17
17
  SEARCH_POSITION_TRIGGER: 'trigger',
18
- SEARCH_POSITION_CUSTOM: 'custom'
18
+ SEARCH_POSITION_CUSTOM: 'custom',
19
+ RELATED: 'related',
20
+ UN_RELATED: 'unRelated'
19
21
  };
20
22
  const numbers = {};
21
23
  export { cssClasses, strings, numbers };
@@ -112,6 +112,7 @@ export interface BasicCascaderProps {
112
112
  enableLeafClick?: boolean;
113
113
  preventScroll?: boolean;
114
114
  virtualizeInSearch?: Virtualize;
115
+ checkRelation?: string;
115
116
  onClear?: () => void;
116
117
  triggerRender?: (props: BasicTriggerRenderProps) => any;
117
118
  onListScroll?: (e: any, panel: BasicScrollPanelProps) => void;
@@ -228,6 +229,8 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
228
229
  notifyIfLoadData(item: BasicEntity | BasicData): void;
229
230
  handleSingleSelect(e: any, item: BasicEntity | BasicData): void;
230
231
  _handleMultipleSelect(item: BasicEntity | BasicData): void;
232
+ _handleRelatedMultipleSelect(item: BasicEntity | BasicData): void;
233
+ _handleUnRelatedMultipleSelect(item: BasicEntity | BasicData): void;
231
234
  calcNonDisabledCheckedKeys(eventKey: string, targetStatus: boolean): {
232
235
  checkedKeys: Set<string>;
233
236
  halfCheckedKeys: Set<any>;
@@ -595,6 +595,19 @@ export default class CascaderFoundation extends BaseFoundation {
595
595
  }
596
596
  }
597
597
  _handleMultipleSelect(item) {
598
+ const {
599
+ checkRelation
600
+ } = this.getProps();
601
+ if (checkRelation === strings.RELATED) {
602
+ this._handleRelatedMultipleSelect(item);
603
+ } else if (checkRelation === 'unRelated') {
604
+ this._handleUnRelatedMultipleSelect(item);
605
+ }
606
+ this._adapter.updateStates({
607
+ inputValue: ''
608
+ });
609
+ }
610
+ _handleRelatedMultipleSelect(item) {
598
611
  const {
599
612
  key
600
613
  } = item;
@@ -659,9 +672,48 @@ export default class CascaderFoundation extends BaseFoundation {
659
672
  if (curCheckedStatus) {
660
673
  this._notifySelect(curRealCheckedKeys);
661
674
  }
662
- this._adapter.updateStates({
663
- inputValue: ''
664
- });
675
+ }
676
+ _handleUnRelatedMultipleSelect(item) {
677
+ const {
678
+ key
679
+ } = item;
680
+ const {
681
+ checkedKeys,
682
+ keyEntities
683
+ } = this.getStates();
684
+ const {
685
+ max
686
+ } = this.getProps();
687
+ const newCheckedKeys = new Set(checkedKeys);
688
+ let targetStatus;
689
+ const prevCheckedStatus = checkedKeys.has(key);
690
+ if (prevCheckedStatus) {
691
+ newCheckedKeys.delete(key);
692
+ targetStatus = false;
693
+ } else {
694
+ // 查看是否超出 max
695
+ if (_isNumber(max)) {
696
+ if (checkedKeys.size >= max) {
697
+ const checkedEntities = [];
698
+ checkedKeys.forEach(itemKey => {
699
+ checkedEntities.push(keyEntities[itemKey]);
700
+ });
701
+ this._adapter.notifyOnExceed(checkedEntities);
702
+ return;
703
+ }
704
+ }
705
+ newCheckedKeys.add(key);
706
+ targetStatus = true;
707
+ }
708
+ if (!this._isControlledComponent()) {
709
+ this._adapter.updateStates({
710
+ checkedKeys: newCheckedKeys
711
+ });
712
+ }
713
+ this._notifyChange(newCheckedKeys);
714
+ if (targetStatus) {
715
+ this._notifySelect(newCheckedKeys);
716
+ }
665
717
  }
666
718
  calcNonDisabledCheckedKeys(eventKey, targetStatus) {
667
719
  const {
@@ -0,0 +1,45 @@
1
+ import BaseFoundation, { DefaultAdapter } from '../base/foundation';
2
+ export declare function clampValueInRange(value: number, min: number, max: number): number;
3
+ export interface DragMoveAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
4
+ getDragElement: () => HTMLElement;
5
+ getConstrainer: () => HTMLElement | null;
6
+ getHandler: () => HTMLElement;
7
+ notifyMouseDown?: (e: MouseEvent) => void;
8
+ notifyMouseMove?: (e: MouseEvent) => void;
9
+ notifyMouseUp?: (e: MouseEvent) => void;
10
+ notifyTouchStart?: (e: TouchEvent) => void;
11
+ notifyTouchMove?: (e: TouchEvent) => void;
12
+ notifyTouchEnd?: (e: TouchEvent) => void;
13
+ notifyTouchCancel?: (e: TouchEvent) => void;
14
+ }
15
+ export default class DragMoveFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<DragMoveAdapter<P, S>, P, S> {
16
+ element: HTMLElement;
17
+ xMax: number;
18
+ xMin: number;
19
+ yMax: number;
20
+ yMin: number;
21
+ startOffsetX: number;
22
+ startOffsetY: number;
23
+ get constrainer(): HTMLElement;
24
+ get handler(): HTMLElement;
25
+ constructor(adapter: DragMoveAdapter<P, S>);
26
+ init(): void;
27
+ destroy(): void;
28
+ _registerDocMouseEvent: () => void;
29
+ _unRegisterDocMouseEvent: () => void;
30
+ _registerDocTouchEvent: () => void;
31
+ _unRegisterDocTouchEvent: () => void;
32
+ _unRegisterEvent(): void;
33
+ _calcMoveRange(): void;
34
+ _allowMove(e: MouseEvent | TouchEvent): any;
35
+ _calcOffset: (e: Touch | MouseEvent) => void;
36
+ _preventDefault: (e: MouseEvent | TouchEvent) => void;
37
+ onMouseDown: (e: MouseEvent) => void;
38
+ onTouchStart: (e: TouchEvent) => void;
39
+ _changePos: (e: Touch | MouseEvent) => void;
40
+ _onMouseMove: (e: MouseEvent) => void;
41
+ _onTouchMove: (e: TouchEvent) => void;
42
+ _onMouseUp: (e: MouseEvent) => void;
43
+ _onTouchEnd: (e: TouchEvent) => void;
44
+ _onTouchCancel: (e: TouchEvent) => void;
45
+ }
@@ -0,0 +1,153 @@
1
+ import BaseFoundation from '../base/foundation';
2
+ export function clampValueInRange(value, min, max) {
3
+ return Math.min(Math.max(value, min), max);
4
+ }
5
+ export default class DragMoveFoundation extends BaseFoundation {
6
+ get constrainer() {
7
+ return this._adapter.getConstrainer();
8
+ }
9
+ get handler() {
10
+ return this._adapter.getHandler();
11
+ }
12
+ constructor(adapter) {
13
+ super(Object.assign({}, adapter));
14
+ this._registerDocMouseEvent = () => {
15
+ document.addEventListener('mousemove', this._onMouseMove);
16
+ document.addEventListener('mouseup', this._onMouseUp);
17
+ };
18
+ this._unRegisterDocMouseEvent = () => {
19
+ document.removeEventListener('mousemove', this._onMouseMove);
20
+ document.removeEventListener('mouseup', this._onMouseUp);
21
+ };
22
+ this._registerDocTouchEvent = () => {
23
+ document.addEventListener('touchend', this._onTouchEnd);
24
+ document.addEventListener('touchmove', this._onTouchMove);
25
+ document.addEventListener('touchcancel', this._onTouchCancel);
26
+ };
27
+ this._unRegisterDocTouchEvent = () => {
28
+ document.removeEventListener('touchend', this._onTouchEnd);
29
+ document.removeEventListener('touchmove', this._onTouchMove);
30
+ document.removeEventListener('touchcancel', this._onTouchCancel);
31
+ };
32
+ this._calcOffset = e => {
33
+ this.startOffsetX = e.clientX - this.element.offsetLeft;
34
+ this.startOffsetY = e.clientY - this.element.offsetTop;
35
+ };
36
+ this._preventDefault = e => {
37
+ // prevent default behavior, avoid other element(like img, text) be selected
38
+ e.preventDefault();
39
+ };
40
+ this.onMouseDown = e => {
41
+ this._calcMoveRange();
42
+ this._adapter.notifyMouseDown(e);
43
+ if (!this._allowMove(e)) {
44
+ return;
45
+ }
46
+ this._registerDocMouseEvent();
47
+ // store origin offset
48
+ this._calcOffset(e);
49
+ this._preventDefault(e);
50
+ };
51
+ this.onTouchStart = e => {
52
+ this._calcMoveRange();
53
+ this._adapter.notifyTouchStart(e);
54
+ if (!this._allowMove(e)) {
55
+ return;
56
+ }
57
+ this._registerDocTouchEvent();
58
+ const touch = e.targetTouches[0];
59
+ this._calcOffset(touch);
60
+ this._preventDefault(e);
61
+ };
62
+ this._changePos = e => {
63
+ const {
64
+ customMove
65
+ } = this.getProps();
66
+ let newLeft = e.clientX - this.startOffsetX;
67
+ let newTop = e.clientY - this.startOffsetY;
68
+ if (this.constrainer) {
69
+ newLeft = clampValueInRange(newLeft, this.xMin, this.xMax);
70
+ newTop = clampValueInRange(newTop, this.yMin, this.yMax);
71
+ }
72
+ requestAnimationFrame(() => {
73
+ if (customMove) {
74
+ customMove(this.element, newTop, newLeft);
75
+ return;
76
+ }
77
+ this.element.style.top = newTop + 'px';
78
+ this.element.style.left = newLeft + 'px';
79
+ });
80
+ };
81
+ this._onMouseMove = e => {
82
+ this._adapter.notifyMouseMove(e);
83
+ this._changePos(e);
84
+ };
85
+ this._onTouchMove = e => {
86
+ this._adapter.notifyTouchMove(e);
87
+ const touch = e.targetTouches[0];
88
+ this._changePos(touch);
89
+ };
90
+ this._onMouseUp = e => {
91
+ this._adapter.notifyMouseUp(e);
92
+ this._unRegisterDocMouseEvent();
93
+ };
94
+ this._onTouchEnd = e => {
95
+ this._adapter.notifyTouchEnd(e);
96
+ this._unRegisterDocTouchEvent();
97
+ };
98
+ this._onTouchCancel = e => {
99
+ this._adapter.notifyTouchCancel(e);
100
+ this._unRegisterDocTouchEvent();
101
+ };
102
+ }
103
+ init() {
104
+ const element = this._adapter.getDragElement();
105
+ if (!element) {
106
+ throw new Error('drag element must be a valid element');
107
+ }
108
+ this.element = element;
109
+ this.element.style.position = 'absolute';
110
+ this.handler.style.cursor = 'move';
111
+ }
112
+ destroy() {
113
+ this._unRegisterEvent();
114
+ }
115
+ _unRegisterEvent() {
116
+ this._unRegisterDocMouseEvent();
117
+ this._unRegisterDocTouchEvent();
118
+ }
119
+ _calcMoveRange() {
120
+ // Calculate the range within which an element can move
121
+ if (this.constrainer) {
122
+ let node = this.element.offsetParent;
123
+ let startX = 0;
124
+ let startY = 0;
125
+ while (node !== this.constrainer && node !== null) {
126
+ startX -= node.offsetLeft;
127
+ startY -= node.offsetTop;
128
+ node = node.offsetParent;
129
+ }
130
+ this.xMin = startX;
131
+ this.xMax = startX + this.constrainer.offsetWidth - this.element.offsetWidth;
132
+ this.yMin = startY;
133
+ this.yMax = startY + this.constrainer.offsetHeight - this.element.offsetHeight;
134
+ }
135
+ }
136
+ _allowMove(e) {
137
+ const {
138
+ allowMove,
139
+ allowInputDrag
140
+ } = this.getProps();
141
+ // When the clicked object is an input or textarea, clicking should be allowed but dragging should not be allowed.
142
+ if (!allowInputDrag) {
143
+ let target = e.target.tagName.toLowerCase();
144
+ if (target === 'input' || target === 'textarea') {
145
+ return;
146
+ }
147
+ }
148
+ if (allowMove) {
149
+ return allowMove(e, this.element);
150
+ }
151
+ return true;
152
+ }
153
+ }
@@ -0,0 +1,84 @@
1
+ import BaseFoundation, { DefaultAdapter } from '../base/foundation';
2
+ interface HighlightAdapter extends Partial<DefaultAdapter> {
3
+ }
4
+ interface ChunkQuery {
5
+ autoEscape?: boolean;
6
+ caseSensitive?: boolean;
7
+ searchWords: SearchWords;
8
+ sourceString: string;
9
+ }
10
+ export interface Chunk {
11
+ start: number;
12
+ end: number;
13
+ highlight: boolean;
14
+ className: string;
15
+ style: Record<string, string>;
16
+ }
17
+ export interface ComplexSearchWord {
18
+ text: string;
19
+ className?: string;
20
+ style?: Record<string, string>;
21
+ }
22
+ export type SearchWord = string | ComplexSearchWord | undefined;
23
+ export type SearchWords = SearchWord[];
24
+ export default class HighlightFoundation extends BaseFoundation<HighlightAdapter> {
25
+ constructor(adapter?: HighlightAdapter);
26
+ /**
27
+ * Creates an array of chunk objects representing both higlightable and non highlightable pieces of text that match each search word.
28
+ *
29
+ findAll ['z'], 'aaazaaazaaa'
30
+ result #=> [
31
+ { start: 0, end: 3, highlight: false }
32
+ { start: 3, end: 4, highlight: true }
33
+ { start: 4, end: 7, highlight: false }
34
+ { start: 7, end: 8, highlight: true }
35
+ { start: 8, end: 11, highlight: false }
36
+ ]
37
+
38
+ findAll ['do', 'dollar'], 'aaa do dollar aaa'
39
+ #=> chunks: [
40
+ { start: 4, end: 6 },
41
+ { start: 7, end: 9 },
42
+ { start: 7, end: 13 },
43
+ ]
44
+ #=> chunksToHight: [
45
+ { start: 4, end: 6 },
46
+ { start: 7, end: 13 },
47
+ ]
48
+ #=> result: [
49
+ { start: 0, end: 4, highlight: false },
50
+ { start: 4, end: 6, highlight: true },
51
+ { start: 6, end: 7, highlight: false },
52
+ { start: 7, end: 13, highlight: true },
53
+ { start: 13, end: 17, highlight: false },
54
+ ]
55
+
56
+ * @return Array of "chunks" (where a Chunk is { start:number, end:number, highlight:boolean })
57
+ */
58
+ findAll: ({ autoEscape, caseSensitive, searchWords, sourceString }: ChunkQuery) => Chunk[];
59
+ /**
60
+ * Examine text for any matches.
61
+ * If we find matches, add them to the returned array as a "chunk" object ({start:number, end:number}).
62
+ * @return { start:number, end:number }[]
63
+ */
64
+ findChunks: ({ autoEscape, caseSensitive, searchWords, sourceString }: ChunkQuery) => Chunk[];
65
+ /**
66
+ * Takes an array of {start:number, end:number} objects and combines chunks that overlap into single chunks.
67
+ * @return {start:number, end:number}[]
68
+ */
69
+ combineChunks: ({ chunks }: {
70
+ chunks: Chunk[];
71
+ }) => Chunk[];
72
+ /**
73
+ * Given a set of chunks to highlight, create an additional set of chunks
74
+ * to represent the bits of text between the highlighted text.
75
+ * @param chunksToHighlight {start:number, end:number}[]
76
+ * @param totalLength number
77
+ * @return {start:number, end:number, highlight:boolean}[]
78
+ */
79
+ fillInChunks: ({ chunksToHighlight, totalLength }: {
80
+ chunksToHighlight: Chunk[];
81
+ totalLength: number;
82
+ }) => Chunk[];
83
+ }
84
+ export {};
@@ -0,0 +1,174 @@
1
+ import _isString from "lodash/isString"; // Modified version based on 'highlight-words-core'
2
+ import BaseFoundation from '../base/foundation';
3
+ const escapeRegExpFn = string => string.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
4
+ export default class HighlightFoundation extends BaseFoundation {
5
+ constructor(adapter) {
6
+ super(Object.assign({}, adapter));
7
+ /**
8
+ * Creates an array of chunk objects representing both higlightable and non highlightable pieces of text that match each search word.
9
+ *
10
+ findAll ['z'], 'aaazaaazaaa'
11
+ result #=> [
12
+ { start: 0, end: 3, highlight: false }
13
+ { start: 3, end: 4, highlight: true }
14
+ { start: 4, end: 7, highlight: false }
15
+ { start: 7, end: 8, highlight: true }
16
+ { start: 8, end: 11, highlight: false }
17
+ ]
18
+ findAll ['do', 'dollar'], 'aaa do dollar aaa'
19
+ #=> chunks: [
20
+ { start: 4, end: 6 },
21
+ { start: 7, end: 9 },
22
+ { start: 7, end: 13 },
23
+ ]
24
+ #=> chunksToHight: [
25
+ { start: 4, end: 6 },
26
+ { start: 7, end: 13 },
27
+ ]
28
+ #=> result: [
29
+ { start: 0, end: 4, highlight: false },
30
+ { start: 4, end: 6, highlight: true },
31
+ { start: 6, end: 7, highlight: false },
32
+ { start: 7, end: 13, highlight: true },
33
+ { start: 13, end: 17, highlight: false },
34
+ ]
35
+ * @return Array of "chunks" (where a Chunk is { start:number, end:number, highlight:boolean })
36
+ */
37
+ this.findAll = _ref => {
38
+ let {
39
+ autoEscape = true,
40
+ caseSensitive = false,
41
+ searchWords,
42
+ sourceString
43
+ } = _ref;
44
+ if (_isString(searchWords)) {
45
+ searchWords = [searchWords];
46
+ }
47
+ const chunks = this.findChunks({
48
+ autoEscape,
49
+ caseSensitive,
50
+ searchWords,
51
+ sourceString
52
+ });
53
+ const chunksToHighlight = this.combineChunks({
54
+ chunks
55
+ });
56
+ const result = this.fillInChunks({
57
+ chunksToHighlight,
58
+ totalLength: sourceString ? sourceString.length : 0
59
+ });
60
+ return result;
61
+ };
62
+ /**
63
+ * Examine text for any matches.
64
+ * If we find matches, add them to the returned array as a "chunk" object ({start:number, end:number}).
65
+ * @return { start:number, end:number }[]
66
+ */
67
+ this.findChunks = _ref2 => {
68
+ let {
69
+ autoEscape,
70
+ caseSensitive,
71
+ searchWords,
72
+ sourceString
73
+ } = _ref2;
74
+ return searchWords.map(searchWord => typeof searchWord === 'string' ? {
75
+ text: searchWord
76
+ } : searchWord).filter(searchWord => searchWord.text) // Remove empty words
77
+ .reduce((chunks, searchWord) => {
78
+ let searchText = searchWord.text;
79
+ if (autoEscape) {
80
+ searchText = escapeRegExpFn(searchText);
81
+ }
82
+ const regex = new RegExp(searchText, caseSensitive ? 'g' : 'gi');
83
+ let match;
84
+ while (match = regex.exec(sourceString)) {
85
+ const start = match.index;
86
+ const end = regex.lastIndex;
87
+ if (end > start) {
88
+ chunks.push({
89
+ highlight: true,
90
+ start,
91
+ end,
92
+ className: searchWord.className,
93
+ style: searchWord.style
94
+ });
95
+ }
96
+ if (match.index === regex.lastIndex) {
97
+ regex.lastIndex++;
98
+ }
99
+ }
100
+ return chunks;
101
+ }, []);
102
+ };
103
+ /**
104
+ * Takes an array of {start:number, end:number} objects and combines chunks that overlap into single chunks.
105
+ * @return {start:number, end:number}[]
106
+ */
107
+ this.combineChunks = _ref3 => {
108
+ let {
109
+ chunks
110
+ } = _ref3;
111
+ return chunks.sort((first, second) => first.start - second.start).reduce((processedChunks, nextChunk) => {
112
+ // First chunk just goes straight in the array...
113
+ if (processedChunks.length === 0) {
114
+ return [nextChunk];
115
+ } else {
116
+ // ... subsequent chunks get checked to see if they overlap...
117
+ const prevChunk = processedChunks.pop();
118
+ if (nextChunk.start <= prevChunk.end) {
119
+ // It may be the case that prevChunk completely surrounds nextChunk, so take the
120
+ // largest of the end indeces.
121
+ const endIndex = Math.max(prevChunk.end, nextChunk.end);
122
+ processedChunks.push({
123
+ highlight: true,
124
+ start: prevChunk.start,
125
+ end: endIndex,
126
+ className: prevChunk.className || nextChunk.className,
127
+ style: Object.assign(Object.assign({}, prevChunk.style), nextChunk.style)
128
+ });
129
+ } else {
130
+ processedChunks.push(prevChunk, nextChunk);
131
+ }
132
+ return processedChunks;
133
+ }
134
+ }, []);
135
+ };
136
+ /**
137
+ * Given a set of chunks to highlight, create an additional set of chunks
138
+ * to represent the bits of text between the highlighted text.
139
+ * @param chunksToHighlight {start:number, end:number}[]
140
+ * @param totalLength number
141
+ * @return {start:number, end:number, highlight:boolean}[]
142
+ */
143
+ this.fillInChunks = _ref4 => {
144
+ let {
145
+ chunksToHighlight,
146
+ totalLength
147
+ } = _ref4;
148
+ const allChunks = [];
149
+ const append = (start, end, highlight, className, style) => {
150
+ if (end - start > 0) {
151
+ allChunks.push({
152
+ start,
153
+ end,
154
+ highlight,
155
+ className,
156
+ style
157
+ });
158
+ }
159
+ };
160
+ if (chunksToHighlight.length === 0) {
161
+ append(0, totalLength, false);
162
+ } else {
163
+ let lastIndex = 0;
164
+ chunksToHighlight.forEach(chunk => {
165
+ append(lastIndex, chunk.start, false);
166
+ append(chunk.start, chunk.end, true, chunk.className, chunk.style);
167
+ lastIndex = chunk.end;
168
+ });
169
+ append(lastIndex, totalLength, false);
170
+ }
171
+ return allChunks;
172
+ };
173
+ }
174
+ }
@@ -0,0 +1,4 @@
1
+ declare const cssClasses: {
2
+ readonly PREFIX: "semi-json-viewer";
3
+ };
4
+ export { cssClasses };
@@ -0,0 +1,5 @@
1
+ import { BASE_CLASS_PREFIX } from "../base/constants";
2
+ const cssClasses = {
3
+ PREFIX: `${BASE_CLASS_PREFIX}-json-viewer`
4
+ };
5
+ export { cssClasses };
@@ -0,0 +1,24 @@
1
+ import { JsonViewer, JsonViewerOptions } from '@douyinfe/semi-json-viewer-core';
2
+ import BaseFoundation, { DefaultAdapter } from '../base/foundation';
3
+ export type { JsonViewerOptions };
4
+ export interface JsonViewerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
5
+ getEditorRef: () => HTMLElement;
6
+ getSearchRef: () => HTMLInputElement;
7
+ notifyChange: (value: string) => void;
8
+ notifyHover: (value: string, el: HTMLElement) => HTMLElement | undefined;
9
+ setSearchOptions: (key: string) => void;
10
+ showSearchBar: () => void;
11
+ }
12
+ declare class JsonViewerFoundation extends BaseFoundation<JsonViewerAdapter> {
13
+ constructor(adapter: JsonViewerAdapter);
14
+ jsonViewer: JsonViewer | null;
15
+ init(): void;
16
+ search(searchText: string): void;
17
+ prevSearch(): void;
18
+ nextSearch(): void;
19
+ replace(replaceText: string): void;
20
+ replaceAll(replaceText: string): void;
21
+ setSearchOptions(key: string): void;
22
+ showSearchBar(): void;
23
+ }
24
+ export default JsonViewerFoundation;
@@ -0,0 +1,62 @@
1
+ import { JsonViewer } from '@douyinfe/semi-json-viewer-core';
2
+ import BaseFoundation from '../base/foundation';
3
+ class JsonViewerFoundation extends BaseFoundation {
4
+ constructor(adapter) {
5
+ super(Object.assign(Object.assign({}, JsonViewerFoundation), adapter));
6
+ this.jsonViewer = null;
7
+ }
8
+ init() {
9
+ const props = this.getProps();
10
+ const editorRef = this._adapter.getEditorRef();
11
+ this.jsonViewer = new JsonViewer(editorRef, props.value, props.options);
12
+ this.jsonViewer.layout();
13
+ this.jsonViewer.emitter.on('contentChanged', e => {
14
+ var _a;
15
+ this._adapter.notifyChange((_a = this.jsonViewer) === null || _a === void 0 ? void 0 : _a.getModel().getValue());
16
+ if (this.getState('showSearchBar')) {
17
+ this.search(this._adapter.getSearchRef().value);
18
+ }
19
+ });
20
+ this.jsonViewer.emitter.on('hoverNode', e => {
21
+ const el = this._adapter.notifyHover(e.value, e.target);
22
+ if (el) {
23
+ this.jsonViewer.emitter.emit('renderHoverNode', {
24
+ el
25
+ });
26
+ }
27
+ });
28
+ }
29
+ search(searchText) {
30
+ var _a;
31
+ const state = this.getState('searchOptions');
32
+ const {
33
+ caseSensitive,
34
+ wholeWord,
35
+ regex
36
+ } = state;
37
+ (_a = this.jsonViewer) === null || _a === void 0 ? void 0 : _a.getSearchWidget().search(searchText, caseSensitive, wholeWord, regex);
38
+ }
39
+ prevSearch() {
40
+ var _a;
41
+ (_a = this.jsonViewer) === null || _a === void 0 ? void 0 : _a.getSearchWidget().navigateResults(-1);
42
+ }
43
+ nextSearch() {
44
+ var _a;
45
+ (_a = this.jsonViewer) === null || _a === void 0 ? void 0 : _a.getSearchWidget().navigateResults(1);
46
+ }
47
+ replace(replaceText) {
48
+ var _a;
49
+ (_a = this.jsonViewer) === null || _a === void 0 ? void 0 : _a.getSearchWidget().replace(replaceText);
50
+ }
51
+ replaceAll(replaceText) {
52
+ var _a;
53
+ (_a = this.jsonViewer) === null || _a === void 0 ? void 0 : _a.getSearchWidget().replaceAll(replaceText);
54
+ }
55
+ setSearchOptions(key) {
56
+ this._adapter.setSearchOptions(key);
57
+ }
58
+ showSearchBar() {
59
+ this._adapter.showSearchBar();
60
+ }
61
+ }
62
+ export default JsonViewerFoundation;