@gct-paas/core-web 0.1.4-dev.6 → 0.1.4-dev.8
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.
- package/dist/index.esm.min.mjs +24964 -0
- package/dist/index.min.cjs +59 -12
- package/dist/index.min.css +1 -0
- package/dist/index.system.min.js +59 -12
- package/es/components/assets-svg-icon/assets-svg-icon.css +188 -0
- package/es/components/assets-svg-icon/assets-svg-icon.d.ts +134 -0
- package/es/components/assets-svg-icon/assets-svg-icon.mjs +238 -0
- package/es/components/assets-svg-icon/request.d.ts +2 -0
- package/es/components/assets-svg-icon/request.mjs +51 -0
- package/es/components/assets-svg-icon/utils.d.ts +9 -0
- package/es/components/assets-svg-icon/utils.mjs +21 -0
- package/es/components/assets-svg-icon/validate.d.ts +4 -0
- package/es/components/assets-svg-icon/validate.mjs +43 -0
- package/es/components/code-editor/code-editor.css +67 -0
- package/es/components/code-editor/code-editor.d.ts +35 -0
- package/es/components/code-editor/code-editor.mjs +15 -20
- package/es/components/index.d.ts +1 -0
- package/es/components/layout/flex-container/flex-container.css +67 -0
- package/es/components/layout/flex-container/flex-container.d.ts +4 -4
- package/es/components/layout/flex-item/flex-item.d.ts +4 -4
- package/es/components/layout/grid-container/grid-container.d.ts +4 -4
- package/es/components/layout/view-container/view-container.css +83 -0
- package/es/components/layout/view-container/view-container.d.ts +4 -4
- package/es/editor/gct-form-check-switch/gct-form-check-switch.d.ts +7 -7
- package/es/editor/gct-form-checkbox/gct-form-checkbox.d.ts +6 -6
- package/es/editor/gct-form-field-select/gct-form-field-select.d.ts +17 -7
- package/es/editor/gct-form-field-select/gct-model-select.vue.d.ts +3 -12
- package/es/editor/gct-form-i18n/gct-form-i18n.d.ts +8 -8
- package/es/editor/gct-form-icon-select/gct-form-icon-select.d.ts +8 -8
- package/es/editor/gct-form-info/gct-form-info.d.ts +7 -7
- package/es/editor/gct-form-length-unit/gct-form-length-unit.d.ts +6 -6
- package/es/editor/gct-form-modal-select/gct-form-modal-select.d.ts +8 -8
- package/es/editor/gct-form-number/gct-form-number.d.ts +7 -7
- package/es/editor/gct-form-picker/gct-form-picker.d.ts +8 -8
- package/es/editor/gct-form-radio/gct-form-radio.d.ts +7 -7
- package/es/editor/gct-form-select/gct-form-select.d.ts +7 -7
- package/es/editor/gct-form-span/gct-form-span.d.ts +5 -5
- package/es/editor/gct-form-switch/gct-form-switch.d.ts +6 -6
- package/es/editor/gct-form-text/gct-form-text.d.ts +7 -7
- package/es/editor/gct-form-textarea/gct-form-textarea.d.ts +7 -7
- package/es/hooks/index.d.ts +2 -0
- package/es/hooks/useLocale.d.ts +4 -0
- package/es/hooks/useLocale.mjs +32 -0
- package/es/hooks/useTheme.d.ts +8 -0
- package/es/hooks/useTheme.mjs +20 -0
- package/es/index.d.ts +5 -6
- package/es/index.mjs +19 -24
- package/es/modules/gct-dnd/components/gct-dnd-container/gct-dnd-container.css +72 -0
- package/es/modules/gct-dnd/components/gct-dnd-container/gct-dnd-container.d.ts +37 -0
- package/es/modules/gct-dnd/components/gct-dnd-container/gct-dnd-container.mjs +195 -0
- package/es/modules/gct-dnd/components/gct-dnd-drop-line/gct-dnd-drop-line.css +79 -0
- package/es/modules/gct-dnd/components/gct-dnd-drop-line/gct-dnd-drop-line.d.ts +29 -0
- package/es/modules/gct-dnd/components/gct-dnd-drop-line/gct-dnd-drop-line.mjs +98 -0
- package/es/modules/gct-dnd/components/gct-dnd-item/gct-dnd-item.css +70 -0
- package/es/modules/gct-dnd/components/gct-dnd-item/gct-dnd-item.d.ts +50 -0
- package/es/modules/gct-dnd/components/gct-dnd-item/gct-dnd-item.mjs +239 -0
- package/es/modules/gct-dnd/constants/index.d.ts +24 -0
- package/es/modules/gct-dnd/constants/index.mjs +9 -0
- package/es/modules/gct-dnd/index.d.ts +5 -0
- package/es/modules/gct-dnd/interface/i-gct-dnd-config.d.ts +101 -0
- package/es/modules/gct-dnd/interface/i-gct-dnd-data.d.ts +14 -0
- package/es/modules/gct-dnd/interface/i-gct-dnd-render-item-options.d.ts +28 -0
- package/es/modules/gct-dnd/interface/i-gct-drag-collect.d.ts +24 -0
- package/es/modules/gct-dnd/interface/i-gct-drag-dnd-data.d.ts +51 -0
- package/es/modules/gct-dnd/interface/i-gct-drop-collect.d.ts +32 -0
- package/es/modules/gct-dnd/interface/i-gct-drop-result.d.ts +47 -0
- package/es/modules/gct-dnd/interface/index.d.ts +7 -0
- package/es/types/index.d.ts +1 -1
- package/es/utils/with-install.mjs +0 -1
- package/es/widgets/gct-edit-form/gct-edit-form.d.ts +9 -9
- package/es/widgets/gct-form/gct-form-collapse/gct-form-collapse.d.ts +6 -6
- package/es/widgets/gct-form/gct-form-collapse-pane/gct-form-collapse-pane.d.ts +4 -4
- package/es/widgets/gct-form/gct-form-group/gct-form-group.d.ts +5 -5
- package/es/widgets/gct-form/gct-form-item/gct-form-item.d.ts +4 -4
- package/es/widgets/gct-form/gct-form-tab/gct-form-tab.d.ts +4 -4
- package/es/widgets/gct-form/gct-form-tab-pane/gct-form-tab-pane.d.ts +4 -4
- package/es/widgets/gct-form/gct-form-title-group/gct-form-title-group.d.ts +5 -5
- package/es/widgets/gct-form/gct-form.d.ts +5 -5
- package/package.json +15 -13
- package/dist/core-web.css +0 -1
- package/es/components/code-editor/code-editor.scss +0 -3
- package/es/components/index.mjs +0 -7
- package/es/components/layout/flex-container/flex-container.mjs +0 -90
- package/es/components/layout/flex-container/flex-container.scss +0 -3
- package/es/components/layout/flex-item/flex-item.mjs +0 -53
- package/es/components/layout/flex-item/flex-item.scss +0 -17
- package/es/components/layout/grid-container/grid-container.mjs +0 -47
- package/es/components/layout/view-container/view-container.mjs +0 -39
- package/es/components/layout/view-container/view-container.scss +0 -19
- package/es/editor/gct-form-check-switch/gct-form-check-switch.mjs +0 -53
- package/es/editor/gct-form-check-switch/gct-form-check-switch.provider.mjs +0 -6
- package/es/editor/gct-form-check-switch/gct-form-check-switch.scss +0 -10
- package/es/editor/gct-form-check-switch/index.mjs +0 -12
- package/es/editor/gct-form-checkbox/gct-form-checkbox.mjs +0 -70
- package/es/editor/gct-form-checkbox/gct-form-checkbox.scss +0 -56
- package/es/editor/gct-form-checkbox/index.mjs +0 -19
- package/es/editor/gct-form-color/gct-form-color.mjs +0 -45
- package/es/editor/gct-form-color/gct-form-color.provider.mjs +0 -6
- package/es/editor/gct-form-color/gct-form-color.scss +0 -3
- package/es/editor/gct-form-color/index.mjs +0 -17
- package/es/editor/gct-form-field-select/gct-form-field-select.mjs +0 -48
- package/es/editor/gct-form-field-select/gct-form-field-select.provider.mjs +0 -6
- package/es/editor/gct-form-field-select/gct-form-field-select.scss +0 -7
- package/es/editor/gct-form-field-select/gct-model-select.vue +0 -70
- package/es/editor/gct-form-field-select/index.mjs +0 -12
- package/es/editor/gct-form-i18n/gct-form-i18n.mjs +0 -62
- package/es/editor/gct-form-i18n/gct-form-i18n.provider.mjs +0 -6
- package/es/editor/gct-form-i18n/index.mjs +0 -12
- package/es/editor/gct-form-icon-select/gct-form-icon-select.mjs +0 -74
- package/es/editor/gct-form-icon-select/gct-form-icon-select.scss +0 -14
- package/es/editor/gct-form-icon-select/index.mjs +0 -14
- package/es/editor/gct-form-info/gct-form-info.mjs +0 -40
- package/es/editor/gct-form-info/gct-form-info.scss +0 -8
- package/es/editor/gct-form-info/index.mjs +0 -14
- package/es/editor/gct-form-length-unit/gct-form-length-unit.mjs +0 -43
- package/es/editor/gct-form-length-unit/gct-form-length-unit.provider.mjs +0 -6
- package/es/editor/gct-form-length-unit/index.mjs +0 -12
- package/es/editor/gct-form-modal-select/gct-form-modal-select.mjs +0 -99
- package/es/editor/gct-form-modal-select/gct-form-modal-select.provider.mjs +0 -6
- package/es/editor/gct-form-modal-select/gct-form-modal-select.scss +0 -7
- package/es/editor/gct-form-modal-select/index.mjs +0 -12
- package/es/editor/gct-form-number/gct-form-number.mjs +0 -44
- package/es/editor/gct-form-number/gct-form-number.provider.mjs +0 -6
- package/es/editor/gct-form-number/gct-form-number.scss +0 -3
- package/es/editor/gct-form-number/index.mjs +0 -17
- package/es/editor/gct-form-picker/gct-form-picker.mjs +0 -92
- package/es/editor/gct-form-picker/gct-form-picker.provider.mjs +0 -6
- package/es/editor/gct-form-picker/index.mjs +0 -12
- package/es/editor/gct-form-radio/gct-form-radio.mjs +0 -70
- package/es/editor/gct-form-radio/gct-form-radio.scss +0 -68
- package/es/editor/gct-form-radio/index.mjs +0 -19
- package/es/editor/gct-form-select/gct-form-select.mjs +0 -50
- package/es/editor/gct-form-select/gct-form-select.provider.mjs +0 -6
- package/es/editor/gct-form-select/index.mjs +0 -12
- package/es/editor/gct-form-span/gct-form-span.mjs +0 -89
- package/es/editor/gct-form-span/gct-form-span.provider.mjs +0 -6
- package/es/editor/gct-form-span/gct-form-span.scss +0 -10
- package/es/editor/gct-form-span/index.mjs +0 -12
- package/es/editor/gct-form-switch/gct-form-switch.mjs +0 -35
- package/es/editor/gct-form-switch/gct-form-switch.provider.mjs +0 -6
- package/es/editor/gct-form-switch/index.mjs +0 -17
- package/es/editor/gct-form-text/gct-form-text.mjs +0 -45
- package/es/editor/gct-form-text/gct-form-text.provider.mjs +0 -6
- package/es/editor/gct-form-text/index.mjs +0 -17
- package/es/editor/gct-form-textarea/gct-form-textarea.mjs +0 -40
- package/es/editor/gct-form-textarea/gct-form-textarea.provider.mjs +0 -6
- package/es/editor/gct-form-textarea/index.mjs +0 -12
- package/es/editor/index.mjs +0 -51
- package/es/utils/index.mjs +0 -3
- package/es/vite-env.d.ts +0 -1
- package/es/widgets/gct-edit-form/gct-edit-form.mjs +0 -126
- package/es/widgets/gct-edit-form/index.mjs +0 -10
- package/es/widgets/gct-form/gct-form-collapse/gct-form-collapse.mjs +0 -73
- package/es/widgets/gct-form/gct-form-collapse/gct-form-collapse.provider.mjs +0 -11
- package/es/widgets/gct-form/gct-form-collapse/gct-form-collapse.scss +0 -62
- package/es/widgets/gct-form/gct-form-collapse/index.mjs +0 -15
- package/es/widgets/gct-form/gct-form-collapse-pane/gct-form-collapse-pane.mjs +0 -71
- package/es/widgets/gct-form/gct-form-collapse-pane/gct-form-collapse-pane.provider.mjs +0 -13
- package/es/widgets/gct-form/gct-form-collapse-pane/gct-form-collapse-pane.scss +0 -23
- package/es/widgets/gct-form/gct-form-collapse-pane/index.mjs +0 -15
- package/es/widgets/gct-form/gct-form-group/gct-form-group.mjs +0 -88
- package/es/widgets/gct-form/gct-form-group/gct-form-group.provider.mjs +0 -11
- package/es/widgets/gct-form/gct-form-group/gct-form-group.scss +0 -28
- package/es/widgets/gct-form/gct-form-group/index.mjs +0 -15
- package/es/widgets/gct-form/gct-form-hidden-item/gct-form-hidden-item.provider.mjs +0 -13
- package/es/widgets/gct-form/gct-form-item/gct-form-item.mjs +0 -141
- package/es/widgets/gct-form/gct-form-item/gct-form-item.provider.mjs +0 -11
- package/es/widgets/gct-form/gct-form-item/gct-form-item.scss +0 -115
- package/es/widgets/gct-form/gct-form-tab/gct-form-tab.mjs +0 -53
- package/es/widgets/gct-form/gct-form-tab/gct-form-tab.provider.mjs +0 -11
- package/es/widgets/gct-form/gct-form-tab/gct-form-tab.scss +0 -63
- package/es/widgets/gct-form/gct-form-tab/index.mjs +0 -12
- package/es/widgets/gct-form/gct-form-tab-pane/gct-form-tab-pane.mjs +0 -65
- package/es/widgets/gct-form/gct-form-tab-pane/gct-form-tab-pane.provider.mjs +0 -11
- package/es/widgets/gct-form/gct-form-tab-pane/gct-form-tab-pane.scss +0 -16
- package/es/widgets/gct-form/gct-form-tab-pane/index.mjs +0 -15
- package/es/widgets/gct-form/gct-form-title-group/gct-form-title-group.mjs +0 -71
- package/es/widgets/gct-form/gct-form-title-group/gct-form-title-group.provider.mjs +0 -11
- package/es/widgets/gct-form/gct-form-title-group/gct-form-title-group.scss +0 -25
- package/es/widgets/gct-form/gct-form-title-group/index.mjs +0 -16
- package/es/widgets/gct-form/gct-form.mjs +0 -110
- package/es/widgets/gct-form/gct-form.scss +0 -11
- package/es/widgets/gct-form/index.mjs +0 -31
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
/* stylelint-disable scss/no-global-function-names */
|
|
3
|
+
/* bem('block', 'element', 'modifier') => 'ibiz-block__element--modifier' */
|
|
4
|
+
/**
|
|
5
|
+
* 定义 Block 块
|
|
6
|
+
* @param {String} $block - Block 块名称
|
|
7
|
+
* @example
|
|
8
|
+
* @include b('button') {
|
|
9
|
+
* padding: 10px;
|
|
10
|
+
* }
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* 定义 Element 元素
|
|
14
|
+
* @param {String|List} $element - Element 元素名称,支持单个或多个
|
|
15
|
+
* @example
|
|
16
|
+
* @include b('button') {
|
|
17
|
+
* @include e('text') {
|
|
18
|
+
* color: #000;
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* // 或传入多个元素
|
|
22
|
+
* @include b('button') {
|
|
23
|
+
* @include e(('text', 'icon')) {
|
|
24
|
+
* margin: 5px;
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* 定义 Modifier 修饰符
|
|
30
|
+
* @param {String|List} $modifier - Modifier 修饰符名称,支持单个或多个
|
|
31
|
+
* @example
|
|
32
|
+
* @include b('button') {
|
|
33
|
+
* @include m('primary') {
|
|
34
|
+
* background: blue;
|
|
35
|
+
* }
|
|
36
|
+
* }
|
|
37
|
+
* // 或传入多个修饰符
|
|
38
|
+
* @include b('button') {
|
|
39
|
+
* @include m(('primary', 'large')) {
|
|
40
|
+
* background: blue;
|
|
41
|
+
* font-size: 16px;
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* 定义状态选择器
|
|
47
|
+
* @param {String} $state - 状态名称
|
|
48
|
+
* @example
|
|
49
|
+
* @include b('button') {
|
|
50
|
+
* @include when('disabled') {
|
|
51
|
+
* opacity: 0.5;
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* 深色主题样式
|
|
57
|
+
* @param {String} $block - Block 块名称
|
|
58
|
+
* @example
|
|
59
|
+
* @include dark('button') {
|
|
60
|
+
* background: #333;
|
|
61
|
+
* color: #fff;
|
|
62
|
+
* }
|
|
63
|
+
*/
|
|
64
|
+
/* stylelint-disable scss/no-global-function-names */
|
|
65
|
+
.gct-assets-svg-icon {
|
|
66
|
+
display: inline-block;
|
|
67
|
+
width: 1em;
|
|
68
|
+
height: 1em;
|
|
69
|
+
contain: strict;
|
|
70
|
+
fill: currentcolor;
|
|
71
|
+
box-sizing: content-box !important;
|
|
72
|
+
}
|
|
73
|
+
.gct-assets-svg-icon .ionicon {
|
|
74
|
+
stroke: currentcolor;
|
|
75
|
+
}
|
|
76
|
+
.gct-assets-svg-icon .ionicon-fill-none {
|
|
77
|
+
fill: none;
|
|
78
|
+
}
|
|
79
|
+
.gct-assets-svg-icon .ionicon-stroke-width {
|
|
80
|
+
stroke-width: var(--ionicon-stroke-width, 32px);
|
|
81
|
+
}
|
|
82
|
+
.gct-assets-svg-icon .icon-inner,
|
|
83
|
+
.gct-assets-svg-icon .ionicon,
|
|
84
|
+
.gct-assets-svg-icon svg {
|
|
85
|
+
display: block;
|
|
86
|
+
height: 100%;
|
|
87
|
+
width: 100%;
|
|
88
|
+
}
|
|
89
|
+
.gct-assets-svg-icon {
|
|
90
|
+
/* Icon RTL
|
|
91
|
+
* -----------------------------------------------------------
|
|
92
|
+
*/
|
|
93
|
+
/**
|
|
94
|
+
* Safari <16.4 incorrectly reports
|
|
95
|
+
* that it supports :dir(rtl) when it does not.
|
|
96
|
+
* This @supports statement lets us target
|
|
97
|
+
* WebKit browsers to apply the RTL fallback.
|
|
98
|
+
* -webkit-named-image only exists on WebKit.
|
|
99
|
+
* For WebKit browsers that do support :dir(rtl)
|
|
100
|
+
* (i.e. Safari >= 16.4) then the :dir(rtl)
|
|
101
|
+
* code farther down on the page will take
|
|
102
|
+
* effect and override this fallback.
|
|
103
|
+
*/
|
|
104
|
+
}
|
|
105
|
+
@supports (background: -webkit-named-image(i)) {
|
|
106
|
+
.gct-assets-svg-icon.icon-rtl .icon-inner {
|
|
107
|
+
transform: scaleX(-1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
.gct-assets-svg-icon {
|
|
111
|
+
/**
|
|
112
|
+
* Fallback for browsers that support
|
|
113
|
+
* neither :host-context nor :dir.
|
|
114
|
+
* The icon will not react to dir
|
|
115
|
+
* changes, but it will at least
|
|
116
|
+
* respect the dir on component load.
|
|
117
|
+
*/
|
|
118
|
+
}
|
|
119
|
+
.gct-assets-svg-icon.icon-rtl .icon-inner {
|
|
120
|
+
transform: scaleX(-1);
|
|
121
|
+
}
|
|
122
|
+
.gct-assets-svg-icon {
|
|
123
|
+
/* For Vue components, we use attribute selectors instead of :host-context */
|
|
124
|
+
}
|
|
125
|
+
.gct-assets-svg-icon.flip-rtl[dir=rtl] .icon-inner {
|
|
126
|
+
transform: scaleX(-1);
|
|
127
|
+
}
|
|
128
|
+
@supports selector(:dir(rtl)) {
|
|
129
|
+
.gct-assets-svg-icon.flip-rtl:dir(rtl) .icon-inner {
|
|
130
|
+
transform: scaleX(-1);
|
|
131
|
+
}
|
|
132
|
+
.gct-assets-svg-icon {
|
|
133
|
+
/**
|
|
134
|
+
* This is needed for WebKit otherwise the fallback
|
|
135
|
+
* will always cause the icon to be flipped if the document
|
|
136
|
+
* loads in RTL.
|
|
137
|
+
*/
|
|
138
|
+
}
|
|
139
|
+
.gct-assets-svg-icon.flip-rtl:dir(ltr) .icon-inner {
|
|
140
|
+
transform: scaleX(1);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
.gct-assets-svg-icon {
|
|
144
|
+
/* Icon Sizes
|
|
145
|
+
* -----------------------------------------------------------
|
|
146
|
+
*/
|
|
147
|
+
}
|
|
148
|
+
.gct-assets-svg-icon.icon-small {
|
|
149
|
+
font-size: 1.125rem !important;
|
|
150
|
+
}
|
|
151
|
+
.gct-assets-svg-icon.icon-large {
|
|
152
|
+
font-size: 2rem !important;
|
|
153
|
+
}
|
|
154
|
+
.gct-assets-svg-icon {
|
|
155
|
+
/* Icon Colors
|
|
156
|
+
* -----------------------------------------------------------
|
|
157
|
+
*/
|
|
158
|
+
}
|
|
159
|
+
.gct-assets-svg-icon.ion-color {
|
|
160
|
+
color: var(--ion-color-base) !important;
|
|
161
|
+
}
|
|
162
|
+
.gct-assets-svg-icon.ion-color-primary {
|
|
163
|
+
--ion-color-base: var(--ion-color-primary, #3880ff) !important;
|
|
164
|
+
}
|
|
165
|
+
.gct-assets-svg-icon.ion-color-secondary {
|
|
166
|
+
--ion-color-base: var(--ion-color-secondary, #3dc2ff) !important;
|
|
167
|
+
}
|
|
168
|
+
.gct-assets-svg-icon.ion-color-tertiary {
|
|
169
|
+
--ion-color-base: var(--ion-color-tertiary, #5260ff) !important;
|
|
170
|
+
}
|
|
171
|
+
.gct-assets-svg-icon.ion-color-success {
|
|
172
|
+
--ion-color-base: var(--ion-color-success, #2dd36f) !important;
|
|
173
|
+
}
|
|
174
|
+
.gct-assets-svg-icon.ion-color-warning {
|
|
175
|
+
--ion-color-base: var(--ion-color-warning, #ffc409) !important;
|
|
176
|
+
}
|
|
177
|
+
.gct-assets-svg-icon.ion-color-danger {
|
|
178
|
+
--ion-color-base: var(--ion-color-danger, #eb445a) !important;
|
|
179
|
+
}
|
|
180
|
+
.gct-assets-svg-icon.ion-color-light {
|
|
181
|
+
--ion-color-base: var(--ion-color-light, #f4f5f8) !important;
|
|
182
|
+
}
|
|
183
|
+
.gct-assets-svg-icon.ion-color-medium {
|
|
184
|
+
--ion-color-base: var(--ion-color-medium, #92949c) !important;
|
|
185
|
+
}
|
|
186
|
+
.gct-assets-svg-icon.ion-color-dark {
|
|
187
|
+
--ion-color-base: var(--ion-color-dark, #222428) !important;
|
|
188
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG图标组件 - 简化版本 (仅浏览器环境)
|
|
3
|
+
*
|
|
4
|
+
* 此组件是基于Stencil ion-icon组件简化的Vue实现,
|
|
5
|
+
* 专门用于浏览器环境,仅支持通过src属性加载SVG。
|
|
6
|
+
*
|
|
7
|
+
* ## 功能
|
|
8
|
+
* - 支持通过直接URL加载SVG图标
|
|
9
|
+
* - 支持懒加载
|
|
10
|
+
* - 支持RTL文本方向自动翻转
|
|
11
|
+
* - 支持颜色和大小变化
|
|
12
|
+
* - 支持SVG内容安全检查
|
|
13
|
+
*
|
|
14
|
+
* ## 使用示例
|
|
15
|
+
*
|
|
16
|
+
* // 使用 src 属性
|
|
17
|
+
* <SvgIcon src="/path/to/icon.svg" />
|
|
18
|
+
*
|
|
19
|
+
* // 设置大小和颜色
|
|
20
|
+
* <SvgIcon src="/path/to/icon.svg" size="large" color="primary" />
|
|
21
|
+
*
|
|
22
|
+
* // RTL 支持
|
|
23
|
+
* <SvgIcon src="/path/to/icon.svg" flipRtl={true} />
|
|
24
|
+
*
|
|
25
|
+
* // 懒加载
|
|
26
|
+
* <SvgIcon src="/path/to/icon.svg" lazy={true} />
|
|
27
|
+
*
|
|
28
|
+
* // 禁用 SVG 清理
|
|
29
|
+
* <SvgIcon src="/path/to/icon.svg" sanitize={false} />
|
|
30
|
+
*/
|
|
31
|
+
export declare const AssetsSvgIcon: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
|
|
32
|
+
/**
|
|
33
|
+
* The color to use for the background of the item.
|
|
34
|
+
*/
|
|
35
|
+
color: {
|
|
36
|
+
type: StringConstructor;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Specifies whether the icon should horizontally flip when `dir` is `"rtl"`.
|
|
40
|
+
*/
|
|
41
|
+
flipRtl: {
|
|
42
|
+
type: BooleanConstructor;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Specifies the exact `src` of an SVG file to use.
|
|
46
|
+
*/
|
|
47
|
+
src: {
|
|
48
|
+
type: StringConstructor;
|
|
49
|
+
required: true;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* The size of the icon.
|
|
53
|
+
* Available options are: `"small"` and `"large"`.
|
|
54
|
+
*/
|
|
55
|
+
size: {
|
|
56
|
+
type: StringConstructor;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* If enabled, ion-icon will be loaded lazily when it's visible in the viewport.
|
|
60
|
+
* Default, `false`.
|
|
61
|
+
*/
|
|
62
|
+
lazy: {
|
|
63
|
+
type: BooleanConstructor;
|
|
64
|
+
default: boolean;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* When set to `false`, SVG content that is HTTP fetched will not be checked
|
|
68
|
+
* if the response SVG content has any `<script>` elements, or any attributes
|
|
69
|
+
* that start with `on`, such as `onclick`.
|
|
70
|
+
* @default true
|
|
71
|
+
*/
|
|
72
|
+
sanitize: {
|
|
73
|
+
type: BooleanConstructor;
|
|
74
|
+
default: boolean;
|
|
75
|
+
};
|
|
76
|
+
}>, {
|
|
77
|
+
ns: import('@gct-paas/core').Namespace;
|
|
78
|
+
svgContent: import('vue').Ref<string | undefined, string | undefined>;
|
|
79
|
+
classes: import('vue').ComputedRef<{
|
|
80
|
+
[x: string]: boolean;
|
|
81
|
+
'flip-rtl': boolean;
|
|
82
|
+
'icon-rtl': boolean;
|
|
83
|
+
'ion-color'?: boolean | undefined;
|
|
84
|
+
}>;
|
|
85
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
|
86
|
+
/**
|
|
87
|
+
* The color to use for the background of the item.
|
|
88
|
+
*/
|
|
89
|
+
color: {
|
|
90
|
+
type: StringConstructor;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Specifies whether the icon should horizontally flip when `dir` is `"rtl"`.
|
|
94
|
+
*/
|
|
95
|
+
flipRtl: {
|
|
96
|
+
type: BooleanConstructor;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Specifies the exact `src` of an SVG file to use.
|
|
100
|
+
*/
|
|
101
|
+
src: {
|
|
102
|
+
type: StringConstructor;
|
|
103
|
+
required: true;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* The size of the icon.
|
|
107
|
+
* Available options are: `"small"` and `"large"`.
|
|
108
|
+
*/
|
|
109
|
+
size: {
|
|
110
|
+
type: StringConstructor;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* If enabled, ion-icon will be loaded lazily when it's visible in the viewport.
|
|
114
|
+
* Default, `false`.
|
|
115
|
+
*/
|
|
116
|
+
lazy: {
|
|
117
|
+
type: BooleanConstructor;
|
|
118
|
+
default: boolean;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* When set to `false`, SVG content that is HTTP fetched will not be checked
|
|
122
|
+
* if the response SVG content has any `<script>` elements, or any attributes
|
|
123
|
+
* that start with `on`, such as `onclick`.
|
|
124
|
+
* @default true
|
|
125
|
+
*/
|
|
126
|
+
sanitize: {
|
|
127
|
+
type: BooleanConstructor;
|
|
128
|
+
default: boolean;
|
|
129
|
+
};
|
|
130
|
+
}>> & Readonly<{}>, {
|
|
131
|
+
flipRtl: boolean;
|
|
132
|
+
lazy: boolean;
|
|
133
|
+
sanitize: boolean;
|
|
134
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { defineComponent, createVNode, getCurrentInstance, ref, onMounted, nextTick, onUnmounted, watch, computed } from 'vue';
|
|
2
|
+
import { useNamespace } from '@gct-paas/core';
|
|
3
|
+
import { ioniconContent, getSvgContent } from './request.mjs';
|
|
4
|
+
import { isRTL, getSrc } from './utils.mjs';
|
|
5
|
+
import './assets-svg-icon.css';/* empty css */
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Create color classes for the icon.
|
|
9
|
+
* @param color - The color of the icon.
|
|
10
|
+
* @returns The color classes for the icon.
|
|
11
|
+
*/
|
|
12
|
+
const createColorClasses = color => {
|
|
13
|
+
return color ? {
|
|
14
|
+
'ion-color': true,
|
|
15
|
+
[`ion-color-${color}`]: true
|
|
16
|
+
} : null;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* SVG图标组件 - 简化版本 (仅浏览器环境)
|
|
21
|
+
*
|
|
22
|
+
* 此组件是基于Stencil ion-icon组件简化的Vue实现,
|
|
23
|
+
* 专门用于浏览器环境,仅支持通过src属性加载SVG。
|
|
24
|
+
*
|
|
25
|
+
* ## 功能
|
|
26
|
+
* - 支持通过直接URL加载SVG图标
|
|
27
|
+
* - 支持懒加载
|
|
28
|
+
* - 支持RTL文本方向自动翻转
|
|
29
|
+
* - 支持颜色和大小变化
|
|
30
|
+
* - 支持SVG内容安全检查
|
|
31
|
+
*
|
|
32
|
+
* ## 使用示例
|
|
33
|
+
*
|
|
34
|
+
* // 使用 src 属性
|
|
35
|
+
* <SvgIcon src="/path/to/icon.svg" />
|
|
36
|
+
*
|
|
37
|
+
* // 设置大小和颜色
|
|
38
|
+
* <SvgIcon src="/path/to/icon.svg" size="large" color="primary" />
|
|
39
|
+
*
|
|
40
|
+
* // RTL 支持
|
|
41
|
+
* <SvgIcon src="/path/to/icon.svg" flipRtl={true} />
|
|
42
|
+
*
|
|
43
|
+
* // 懒加载
|
|
44
|
+
* <SvgIcon src="/path/to/icon.svg" lazy={true} />
|
|
45
|
+
*
|
|
46
|
+
* // 禁用 SVG 清理
|
|
47
|
+
* <SvgIcon src="/path/to/icon.svg" sanitize={false} />
|
|
48
|
+
*/
|
|
49
|
+
const AssetsSvgIcon = /* @__PURE__ */ defineComponent({
|
|
50
|
+
name: 'AssetsSvgIcon',
|
|
51
|
+
props: {
|
|
52
|
+
/**
|
|
53
|
+
* The color to use for the background of the item.
|
|
54
|
+
*/
|
|
55
|
+
color: {
|
|
56
|
+
type: String
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Specifies whether the icon should horizontally flip when `dir` is `"rtl"`.
|
|
60
|
+
*/
|
|
61
|
+
flipRtl: {
|
|
62
|
+
type: Boolean
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* Specifies the exact `src` of an SVG file to use.
|
|
66
|
+
*/
|
|
67
|
+
src: {
|
|
68
|
+
type: String,
|
|
69
|
+
required: true
|
|
70
|
+
},
|
|
71
|
+
/**
|
|
72
|
+
* The size of the icon.
|
|
73
|
+
* Available options are: `"small"` and `"large"`.
|
|
74
|
+
*/
|
|
75
|
+
size: {
|
|
76
|
+
type: String
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* If enabled, ion-icon will be loaded lazily when it's visible in the viewport.
|
|
80
|
+
* Default, `false`.
|
|
81
|
+
*/
|
|
82
|
+
lazy: {
|
|
83
|
+
type: Boolean,
|
|
84
|
+
default: false
|
|
85
|
+
},
|
|
86
|
+
/**
|
|
87
|
+
* When set to `false`, SVG content that is HTTP fetched will not be checked
|
|
88
|
+
* if the response SVG content has any `<script>` elements, or any attributes
|
|
89
|
+
* that start with `on`, such as `onclick`.
|
|
90
|
+
* @default true
|
|
91
|
+
*/
|
|
92
|
+
sanitize: {
|
|
93
|
+
type: Boolean,
|
|
94
|
+
default: true
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
setup(props) {
|
|
98
|
+
const ns = useNamespace('assets-svg-icon');
|
|
99
|
+
const instance = getCurrentInstance();
|
|
100
|
+
|
|
101
|
+
// Private state
|
|
102
|
+
let io;
|
|
103
|
+
const didLoadIcon = ref(false);
|
|
104
|
+
|
|
105
|
+
// Reactive state
|
|
106
|
+
const svgContent = ref(undefined);
|
|
107
|
+
const isVisible = ref(false);
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Wait until the icon is visible in the viewport.
|
|
111
|
+
* @param el - The element to observe.
|
|
112
|
+
* @param rootMargin - The root margin of the observer.
|
|
113
|
+
* @param cb - The callback to call when the element is visible.
|
|
114
|
+
*/
|
|
115
|
+
const waitUntilVisible = (el, rootMargin, cb) => {
|
|
116
|
+
/**
|
|
117
|
+
* IntersectionObserver is a browser API that allows you to observe
|
|
118
|
+
* the visibility of an element relative to a root element. It is
|
|
119
|
+
* supported in all modern browsers, except IE and when server-side
|
|
120
|
+
* rendering.
|
|
121
|
+
*/
|
|
122
|
+
const hasIntersectionObserverSupport = Boolean(typeof window !== 'undefined' && props.lazy && window.IntersectionObserver);
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* browser doesn't support IntersectionObserver
|
|
126
|
+
* so just fallback to always show it
|
|
127
|
+
*/
|
|
128
|
+
if (!hasIntersectionObserverSupport) {
|
|
129
|
+
return cb();
|
|
130
|
+
}
|
|
131
|
+
const intersectionObserver = io = new window.IntersectionObserver(data => {
|
|
132
|
+
if (data[0]?.isIntersecting) {
|
|
133
|
+
intersectionObserver.disconnect();
|
|
134
|
+
io = undefined;
|
|
135
|
+
cb();
|
|
136
|
+
}
|
|
137
|
+
}, {
|
|
138
|
+
rootMargin
|
|
139
|
+
});
|
|
140
|
+
intersectionObserver.observe(el);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Load the icon using only src URL
|
|
145
|
+
*/
|
|
146
|
+
const loadIcon = () => {
|
|
147
|
+
if (typeof window !== 'undefined' && isVisible.value && props.src) {
|
|
148
|
+
const url = getSrc(props.src);
|
|
149
|
+
if (url) {
|
|
150
|
+
if (ioniconContent.has(url)) {
|
|
151
|
+
// sync if it's already loaded
|
|
152
|
+
svgContent.value = ioniconContent.get(url);
|
|
153
|
+
} else {
|
|
154
|
+
// async if it hasn't been loaded
|
|
155
|
+
getSvgContent(url, props.sanitize).then(() => {
|
|
156
|
+
svgContent.value = ioniconContent.get(url);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
didLoadIcon.value = true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Component lifecycle hooks
|
|
165
|
+
onMounted(() => {
|
|
166
|
+
const el = instance?.vnode.el;
|
|
167
|
+
if (el) {
|
|
168
|
+
/**
|
|
169
|
+
* purposely do not return the promise here because loading
|
|
170
|
+
* the svg file should not hold up loading the app
|
|
171
|
+
* only load the svg if it's visible
|
|
172
|
+
*/
|
|
173
|
+
waitUntilVisible(el, '50px', () => {
|
|
174
|
+
isVisible.value = true;
|
|
175
|
+
loadIcon();
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
nextTick(() => {
|
|
179
|
+
if (!didLoadIcon.value) {
|
|
180
|
+
loadIcon();
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
onUnmounted(() => {
|
|
185
|
+
if (io) {
|
|
186
|
+
io.disconnect();
|
|
187
|
+
io = undefined;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Watch for src prop changes
|
|
192
|
+
watch(() => props.src, () => {
|
|
193
|
+
loadIcon();
|
|
194
|
+
});
|
|
195
|
+
const classes = computed(() => {
|
|
196
|
+
const {
|
|
197
|
+
flipRtl,
|
|
198
|
+
size,
|
|
199
|
+
color
|
|
200
|
+
} = props;
|
|
201
|
+
const el = instance?.vnode.el;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* if flipRtl is true, the icon should change direction when `dir` changes
|
|
205
|
+
*/
|
|
206
|
+
const shouldBeFlippable = flipRtl;
|
|
207
|
+
return {
|
|
208
|
+
...createColorClasses(color),
|
|
209
|
+
[`icon-${size}`]: !!size,
|
|
210
|
+
'flip-rtl': shouldBeFlippable,
|
|
211
|
+
'icon-rtl': shouldBeFlippable && isRTL(el),
|
|
212
|
+
[ns.b()]: true
|
|
213
|
+
};
|
|
214
|
+
});
|
|
215
|
+
return {
|
|
216
|
+
ns,
|
|
217
|
+
svgContent,
|
|
218
|
+
classes
|
|
219
|
+
};
|
|
220
|
+
},
|
|
221
|
+
render() {
|
|
222
|
+
const {
|
|
223
|
+
svgContent,
|
|
224
|
+
classes
|
|
225
|
+
} = this;
|
|
226
|
+
return createVNode("div", {
|
|
227
|
+
"role": "img",
|
|
228
|
+
"class": classes
|
|
229
|
+
}, [typeof window !== 'undefined' && svgContent ? createVNode("div", {
|
|
230
|
+
"class": "icon-inner",
|
|
231
|
+
"innerHTML": svgContent
|
|
232
|
+
}, null) : createVNode("div", {
|
|
233
|
+
"class": "icon-inner"
|
|
234
|
+
}, null)]);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
export { AssetsSvgIcon };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { isSvgDataUrl, isEncodedDataUrl, validateContent } from './validate.mjs';
|
|
2
|
+
|
|
3
|
+
const ioniconContent = /* @__PURE__ */ new Map();
|
|
4
|
+
const requests = /* @__PURE__ */ new Map();
|
|
5
|
+
let parser;
|
|
6
|
+
function safeFallback(url) {
|
|
7
|
+
const svg = "";
|
|
8
|
+
ioniconContent.set(url, svg);
|
|
9
|
+
return svg;
|
|
10
|
+
}
|
|
11
|
+
const getSvgContent = (url, sanitize) => {
|
|
12
|
+
const req = requests.get(url);
|
|
13
|
+
if (req) {
|
|
14
|
+
return req;
|
|
15
|
+
}
|
|
16
|
+
if (typeof fetch !== "undefined" && typeof document !== "undefined") {
|
|
17
|
+
if (isSvgDataUrl(url) && isEncodedDataUrl(url)) {
|
|
18
|
+
return Promise.resolve(getSvgByUrl(url));
|
|
19
|
+
}
|
|
20
|
+
return fetchSvg(url, sanitize);
|
|
21
|
+
}
|
|
22
|
+
return Promise.resolve(safeFallback(url));
|
|
23
|
+
};
|
|
24
|
+
function getSvgByUrl(url) {
|
|
25
|
+
if (!parser) {
|
|
26
|
+
parser = new DOMParser();
|
|
27
|
+
}
|
|
28
|
+
const doc = parser.parseFromString(url, "text/html");
|
|
29
|
+
const svg = doc.querySelector("svg");
|
|
30
|
+
if (svg) {
|
|
31
|
+
ioniconContent.set(url, svg.outerHTML);
|
|
32
|
+
return svg.outerHTML;
|
|
33
|
+
}
|
|
34
|
+
throw new Error(`Could not parse svg from ${url}`);
|
|
35
|
+
}
|
|
36
|
+
function fetchSvg(url, sanitize) {
|
|
37
|
+
const req = fetch(url).then((rsp) => {
|
|
38
|
+
return rsp.text().then((svgContent) => {
|
|
39
|
+
if (svgContent && sanitize !== false) {
|
|
40
|
+
svgContent = validateContent(svgContent);
|
|
41
|
+
}
|
|
42
|
+
const svg = svgContent || "";
|
|
43
|
+
ioniconContent.set(url, svg);
|
|
44
|
+
return svg;
|
|
45
|
+
}).catch(() => safeFallback(url));
|
|
46
|
+
}).catch(() => safeFallback(url));
|
|
47
|
+
requests.set(url, req);
|
|
48
|
+
return req;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { getSvgContent, ioniconContent };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const isStr: (val: any) => val is string;
|
|
2
|
+
export declare const isSrc: (str: string) => boolean;
|
|
3
|
+
export declare const getSrc: (src: string | undefined) => string | null;
|
|
4
|
+
/**
|
|
5
|
+
* Returns `true` if the document or host element
|
|
6
|
+
* has a `dir` set to `rtl`. The host value will always
|
|
7
|
+
* take priority over the root document value.
|
|
8
|
+
*/
|
|
9
|
+
export declare const isRTL: (hostEl?: Pick<HTMLElement, "dir">) => boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const isStr = (val) => typeof val === "string";
|
|
2
|
+
const isSrc = (str) => str.length > 0 && /(\/|\.)/.test(str);
|
|
3
|
+
const getSrc = (src) => {
|
|
4
|
+
if (isStr(src)) {
|
|
5
|
+
src = src.trim();
|
|
6
|
+
if (isSrc(src)) {
|
|
7
|
+
return src;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
};
|
|
12
|
+
const isRTL = (hostEl) => {
|
|
13
|
+
if (hostEl) {
|
|
14
|
+
if (hostEl.dir !== "") {
|
|
15
|
+
return hostEl.dir.toLowerCase() === "rtl";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return document?.dir.toLowerCase() === "rtl";
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { getSrc, isRTL, isSrc, isStr };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { isStr } from './utils.mjs';
|
|
2
|
+
|
|
3
|
+
const validateContent = (svgContent) => {
|
|
4
|
+
const div = document.createElement("div");
|
|
5
|
+
div.innerHTML = svgContent;
|
|
6
|
+
for (let i = div.childNodes.length - 1; i >= 0; i--) {
|
|
7
|
+
if (div.childNodes[i].nodeName.toLowerCase() !== "svg") {
|
|
8
|
+
div.removeChild(div.childNodes[i]);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const svgElm = div.firstElementChild;
|
|
12
|
+
if (svgElm && svgElm.nodeName.toLowerCase() === "svg") {
|
|
13
|
+
const svgClass = svgElm.getAttribute("class") || "";
|
|
14
|
+
svgElm.setAttribute("class", (svgClass + " s-ion-icon").trim());
|
|
15
|
+
if (isValid(svgElm)) {
|
|
16
|
+
return div.innerHTML;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return "";
|
|
20
|
+
};
|
|
21
|
+
const isValid = (elm) => {
|
|
22
|
+
if (elm.nodeType === 1) {
|
|
23
|
+
if (elm.nodeName.toLowerCase() === "script") {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
for (let i = 0; i < elm.attributes.length; i++) {
|
|
27
|
+
const name = elm.attributes[i].name;
|
|
28
|
+
if (isStr(name) && name.toLowerCase().indexOf("on") === 0) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
for (let i = 0; i < elm.childNodes.length; i++) {
|
|
33
|
+
if (!isValid(elm.childNodes[i])) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
};
|
|
40
|
+
const isSvgDataUrl = (url) => url.startsWith("data:image/svg+xml");
|
|
41
|
+
const isEncodedDataUrl = (url) => url.indexOf(";utf8,") !== -1;
|
|
42
|
+
|
|
43
|
+
export { isEncodedDataUrl, isSvgDataUrl, isValid, validateContent };
|