@kanaries/graphic-walker 0.2.11 → 0.2.12

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 (54) hide show
  1. package/dist/App.d.ts +6 -3
  2. package/dist/assets/explainer.worker-8428eb12.js.map +1 -1
  3. package/dist/components/button/base.d.ts +6 -0
  4. package/dist/components/button/default.d.ts +4 -0
  5. package/dist/components/button/primary.d.ts +4 -0
  6. package/dist/dataSource/utils.d.ts +1 -1
  7. package/dist/graphic-walker.es.js +17671 -18577
  8. package/dist/graphic-walker.es.js.map +1 -1
  9. package/dist/graphic-walker.umd.js +134 -134
  10. package/dist/graphic-walker.umd.js.map +1 -1
  11. package/dist/index.d.ts +2 -2
  12. package/dist/interfaces.d.ts +8 -0
  13. package/dist/lib/inferMeta.d.ts +20 -0
  14. package/dist/store/commonStore.d.ts +1 -1
  15. package/dist/store/index.d.ts +0 -1
  16. package/dist/store/visualSpecStore.d.ts +5 -5
  17. package/dist/utils/dataPrep.d.ts +6 -0
  18. package/dist/utils/index.d.ts +2 -2
  19. package/dist/utils/normalization.d.ts +1 -1
  20. package/dist/utils/save.d.ts +3 -3
  21. package/dist/utils/throttle.d.ts +1 -1
  22. package/dist/vis/temporalFormat.d.ts +10 -0
  23. package/package.json +1 -1
  24. package/src/App.tsx +27 -10
  25. package/src/components/button/base.ts +7 -0
  26. package/src/components/button/default.tsx +17 -0
  27. package/src/components/button/primary.tsx +17 -0
  28. package/src/dataSource/dataSelection/csvData.tsx +8 -10
  29. package/src/dataSource/dataSelection/publicData.tsx +4 -4
  30. package/src/dataSource/index.tsx +10 -12
  31. package/src/dataSource/table.tsx +33 -20
  32. package/src/dataSource/utils.ts +30 -35
  33. package/src/fields/datasetFields/dimFields.tsx +1 -5
  34. package/src/fields/datasetFields/meaFields.tsx +1 -5
  35. package/src/fields/obComponents/obFContainer.tsx +1 -5
  36. package/src/index.tsx +3 -4
  37. package/src/interfaces.ts +9 -0
  38. package/src/lib/inferMeta.ts +88 -0
  39. package/src/locales/en-US.json +6 -0
  40. package/src/locales/zh-CN.json +6 -0
  41. package/src/main.tsx +1 -1
  42. package/src/store/commonStore.ts +8 -3
  43. package/src/store/index.tsx +0 -2
  44. package/src/store/visualSpecStore.ts +245 -183
  45. package/src/utils/autoMark.ts +14 -14
  46. package/src/utils/dataPrep.ts +44 -0
  47. package/src/utils/index.ts +140 -128
  48. package/src/utils/normalization.ts +59 -51
  49. package/src/utils/save.ts +22 -21
  50. package/src/utils/throttle.ts +5 -1
  51. package/src/vis/react-vega.tsx +6 -10
  52. package/src/vis/temporalFormat.ts +66 -0
  53. package/dist/pitch/dnd-offset.d.ts +0 -2
  54. package/src/pitch/dnd-offset.ts +0 -64
package/src/utils/save.ts CHANGED
@@ -1,48 +1,49 @@
1
1
  import { IDataSet, IDataSource, IVisSpec } from "../interfaces";
2
2
  import { VisSpecWithHistory } from "../models/visSpecHistory";
3
3
 
4
-
5
- export function dumpsGWPureSpec (list: VisSpecWithHistory[]): IVisSpec[] {
6
- return list.map(l => l.exportGW())
4
+ export function dumpsGWPureSpec(list: VisSpecWithHistory[]): IVisSpec[] {
5
+ return list.map((l) => l.exportGW());
7
6
  }
8
7
 
9
- export function parseGWPureSpec (list: IVisSpec[]): VisSpecWithHistory[] {
10
- return list.map(l => new VisSpecWithHistory(l))
8
+ export function parseGWPureSpec(list: IVisSpec[]): VisSpecWithHistory[] {
9
+ return list.map((l) => new VisSpecWithHistory(l));
11
10
  }
12
11
 
13
12
  interface IStoInfo {
14
13
  datasets: IDataSet[];
15
- specList: ({
14
+ specList: {
16
15
  /** 由于 gw 内部实现暂时未锁版本,这里获取到的信息可能会与当前实例内容有偏差,需要用初始值合入 */
17
- [K in keyof IVisSpec]: K extends 'config' ? Partial<IVisSpec[K]> : IVisSpec[K];
18
- })[];
19
- dataSources: IDataSource[]
16
+ [K in keyof IVisSpec]: K extends "config" ? Partial<IVisSpec[K]> : IVisSpec[K];
17
+ }[];
18
+ dataSources: IDataSource[];
20
19
  }
21
20
 
22
- export function stringifyGWContent (info: IStoInfo) {
23
- return JSON.stringify(info)
21
+ export function stringifyGWContent(info: IStoInfo) {
22
+ return JSON.stringify(info);
24
23
  }
25
24
 
26
- export function parseGWContent (raw: string): IStoInfo {
27
- return JSON.parse(raw)
25
+ export function parseGWContent(raw: string): IStoInfo {
26
+ return JSON.parse(raw);
28
27
  }
29
28
 
30
29
  export function download(data: string, filename: string, type: string) {
31
- var file = new Blob([data], {type: type});
30
+ var file = new Blob([data], { type: type });
32
31
  // @ts-ignore
33
- if (window.navigator.msSaveOrOpenBlob) // IE10+
32
+ if (window.navigator.msSaveOrOpenBlob)
33
+ // IE10+
34
34
  // @ts-ignore
35
35
  window.navigator.msSaveOrOpenBlob(file, filename);
36
- else { // Others
36
+ else {
37
+ // Others
37
38
  var a = document.createElement("a"),
38
- url = URL.createObjectURL(file);
39
+ url = URL.createObjectURL(file);
39
40
  a.href = url;
40
41
  a.download = filename;
41
42
  document.body.appendChild(a);
42
43
  a.click();
43
- setTimeout(function() {
44
+ setTimeout(function () {
44
45
  document.body.removeChild(a);
45
- window.URL.revokeObjectURL(url);
46
- }, 0);
46
+ window.URL.revokeObjectURL(url);
47
+ }, 0);
47
48
  }
48
- }
49
+ }
@@ -1,4 +1,8 @@
1
- const throttle = (fn: () => void, time: number, options?: Partial<{ leading: boolean; trailing: boolean }>): () => void => {
1
+ const throttle = (
2
+ fn: () => void,
3
+ time: number,
4
+ options?: Partial<{ leading: boolean; trailing: boolean }>
5
+ ): (() => void) => {
2
6
  const { leading = true, trailing = false } = options ?? {};
3
7
 
4
8
  let dirty = false;
@@ -9,6 +9,8 @@ import { autoMark } from '../utils/autoMark';
9
9
  import { COUNT_FIELD_ID } from '../constants';
10
10
 
11
11
  import { IViewField, IRow, IStackMode } from '../interfaces';
12
+ import { useTranslation } from 'react-i18next';
13
+ import { getVegaTimeFormatRules } from './temporalFormat';
12
14
 
13
15
  const CanvaContainer = styled.div<{rowSize: number; colSize: number;}>`
14
16
  display: grid;
@@ -119,12 +121,9 @@ function channelEncode(props: EncodeProps) {
119
121
  title: props[c].name,
120
122
  type: props[c].semanticType
121
123
  }
122
- if (props[c].semanticType === 'temporal') {
123
- encoding[c].axis = { format: '%Y-%m' }
124
- }
125
124
  }
126
125
  })
127
- // FIXME: 临时处理逻辑,只处理xy排序
126
+ // FIXME: temporal fix, only for x and y relative order
128
127
  if (encoding.x && encoding.y) {
129
128
  if ((props.x.sort && props.x.sort) || (props.y && props.y.sort)) {
130
129
  if (props.x.sort !== 'none' && (props.y.sort === 'none' || !Boolean(props.y.sort))) {
@@ -383,6 +382,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
383
382
  // const container = useRef<HTMLDivElement>(null);
384
383
  // const containers = useRef<(HTMLDivElement | null)[]>([]);
385
384
  const [viewPlaceholders, setViewPlaceholders] = useState<React.MutableRefObject<HTMLDivElement>[]>([]);
385
+ const { i18n } = useTranslation();
386
386
  useEffect(() => {
387
387
  const clickSub = geomClick$.subscribe(([values, e]) => {
388
388
  if (onGeomClick) {
@@ -502,7 +502,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
502
502
  spec.params.push(...singleView.params!);
503
503
  }
504
504
  if (viewPlaceholders.length > 0 && viewPlaceholders[0].current) {
505
- embed(viewPlaceholders[0].current, spec, { mode: 'vega-lite', actions: showActions }).then(res => {
505
+ embed(viewPlaceholders[0].current, spec, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language) }).then(res => {
506
506
  vegaRefs.current = [res.view];
507
507
  try {
508
508
  res.view.addEventListener('click', (e) => {
@@ -583,10 +583,8 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
583
583
  ans.params = commonSpec.params;
584
584
  }
585
585
  if (node) {
586
- embed(node, ans, { mode: 'vega-lite', actions: showActions }).then(res => {
586
+ embed(node, ans, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language) }).then(res => {
587
587
  vegaRefs.current.push(res.view);
588
- // 这种 case 下,我们来考虑联动的 params
589
- // vega 使用 Data 来维护 params 的状态,只需要打通这些状态就可以实现联动
590
588
  const paramStores = (res.vgSpec.data?.map(d => d.name) ?? []).filter(
591
589
  name => [BRUSH_SIGNAL_NAME, POINT_SIGNAL_NAME].map(p => `${p}_store`).includes(name)
592
590
  ).map(name => name.replace(/_store$/, ''));
@@ -611,12 +609,10 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
611
609
  });
612
610
  }
613
611
  });
614
- // 订阅
615
612
  subscribe(entry => {
616
613
  if (entry.source === sourceId || !entry.data) {
617
614
  return;
618
615
  }
619
- // 防止被动更新触发广播
620
616
  noBroadcasting = true;
621
617
  res.view.setState({
622
618
  data: {
@@ -0,0 +1,66 @@
1
+ export function getVegaTimeFormatRules(lang: string) {
2
+ switch (lang) {
3
+ case 'zh-CN':
4
+ return {
5
+ dateTime: '%x %A %X',
6
+ date: '%Y年%-m月%-d日',
7
+ time: '%H:%M:%S',
8
+ periods: ['上午', '下午'],
9
+ days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
10
+ shortDays: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
11
+ months: [
12
+ '一月',
13
+ '二月',
14
+ '三月',
15
+ '四月',
16
+ '五月',
17
+ '六月',
18
+ '七月',
19
+ '八月',
20
+ '九月',
21
+ '十月',
22
+ '十一月',
23
+ '十二月',
24
+ ],
25
+ shortMonths: [
26
+ '一月',
27
+ '二月',
28
+ '三月',
29
+ '四月',
30
+ '五月',
31
+ '六月',
32
+ '七月',
33
+ '八月',
34
+ '九月',
35
+ '十月',
36
+ '十一月',
37
+ '十二月',
38
+ ],
39
+ };
40
+ case 'en-US':
41
+ default:
42
+ return {
43
+ dateTime: '%x, %X',
44
+ date: '%-m/%-d/%Y',
45
+ time: '%-I:%M:%S %p',
46
+ periods: ['AM', 'PM'],
47
+ days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
48
+ shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
49
+ months: [
50
+ 'January',
51
+ 'February',
52
+ 'March',
53
+ 'April',
54
+ 'May',
55
+ 'June',
56
+ 'July',
57
+ 'August',
58
+ 'September',
59
+ 'October',
60
+ 'November',
61
+ 'December',
62
+ ],
63
+ shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
64
+ };
65
+ }
66
+ }
@@ -1,2 +0,0 @@
1
- import { DraggableProvided } from "react-beautiful-dnd";
2
- export declare function fixDraggableOffset(provided: DraggableProvided, containerDOM: HTMLElement | undefined | null): void;
@@ -1,64 +0,0 @@
1
- import { DraggableProvided } from "react-beautiful-dnd";
2
-
3
- function getElementBoxInfo(ele: HTMLElement) {
4
- const style = window.getComputedStyle(ele);
5
- const borderLeft = parseInt(style.borderLeftWidth);
6
- const paddingLeft = parseInt(style.paddingLeft);
7
- const marginLeft = parseInt(style.marginLeft);
8
- const borderTop = parseInt(style.borderTopWidth);
9
- const paddingTop = parseInt(style.paddingTop);
10
- const marginTop = parseInt(style.marginTop);
11
- return {
12
- borderLeft,
13
- paddingLeft,
14
- marginLeft,
15
- borderTop,
16
- paddingTop,
17
- marginTop,
18
- style
19
- };
20
- }
21
-
22
- export function fixDraggableOffset(provided: DraggableProvided, containerDOM: HTMLElement | undefined | null) {
23
- if (typeof containerDOM === 'undefined' || containerDOM === null) return;
24
- const containerRect = containerDOM.getBoundingClientRect();
25
- const offset = { x: containerRect.left, y: containerRect.top };
26
- let parent: HTMLElement | null = containerDOM.parentElement;
27
- while (parent !== null) {
28
- const box = getElementBoxInfo(parent);
29
- const {
30
- borderLeft: parentBorderLeft,
31
- paddingLeft: parentPaddingLeft,
32
- marginLeft: parentMarginLeft,
33
- borderTop: parentBorderTop,
34
- paddingTop: parentPaddingTop,
35
- marginTop: parentMarginTop,
36
- style
37
- } = box;
38
- offset.x -= ( parentBorderLeft + parentPaddingLeft + parentMarginLeft);
39
- offset.y -= (parentBorderTop + parentPaddingTop + parentMarginTop);
40
- if (style.position === 'absolute' || style.position === 'fixed') {
41
-
42
- break;
43
- }
44
-
45
- parent = parent.parentElement;
46
- }
47
- const root = document.documentElement;
48
- const scrollTop = (window.pageYOffset || root.scrollTop) - (root.clientTop || 0);
49
- const scrollLeft = (window.pageXOffset || root.scrollLeft) - (root.clientLeft || 0);
50
- offset.y += scrollTop;
51
- offset.x += scrollLeft;
52
- //@ts-ignore
53
- const x = (provided.draggableProps.style.left! ?? 0) - offset.x;
54
- //@ts-ignore
55
- const y = (provided.draggableProps.style.top! ?? 0) - offset.y
56
- // TODO: Fix the offset error when there is a layer has padding between fixed layer and provided.draggableProps.style ele.
57
- // the error seems to be 16px which is the pill's height
58
- // provided.draggableProps.style.height;// - 2 - 2 - 1 - 1;
59
-
60
- // @ts-ignore
61
- provided.draggableProps.style.left = x;
62
- // @ts-ignore
63
- provided.draggableProps.style.top = y;
64
- }