@mptw/skylens-ui 1.0.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.
Files changed (143) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintrc.cjs +4 -0
  3. package/.nuxtrc +1 -0
  4. package/.playground/app.config.ts +5 -0
  5. package/.playground/nuxt.config.ts +3 -0
  6. package/README.md +73 -0
  7. package/app.config.ts +5 -0
  8. package/app.vue +3 -0
  9. package/assets/css/fonts/MEShPlus-font-icon.eot +0 -0
  10. package/assets/css/fonts/MEShPlus-font-icon.svg +186 -0
  11. package/assets/css/fonts/MEShPlus-font-icon.ttf +0 -0
  12. package/assets/css/fonts/MEShPlus-font-icon.woff +0 -0
  13. package/assets/css/icons.css +555 -0
  14. package/assets/css/layout.styl +98 -0
  15. package/assets/css/tailwind.css +3 -0
  16. package/assets/images/commons/app-logo-white.png +0 -0
  17. package/assets/images/commons/app-logo.png +0 -0
  18. package/assets/images/commons/empty-box.png +0 -0
  19. package/assets/images/commons/watermark.svg +15 -0
  20. package/components/SLAlertModal.vue +99 -0
  21. package/components/SLBreadcrumbs.vue +42 -0
  22. package/components/SLButton.vue +301 -0
  23. package/components/SLCalendarButton.vue +259 -0
  24. package/components/SLCalendarPopup.vue +832 -0
  25. package/components/SLCard.vue +118 -0
  26. package/components/SLChart.vue +181 -0
  27. package/components/SLCheckbox.vue +179 -0
  28. package/components/SLCircleButton.vue +95 -0
  29. package/components/SLCollapsableBlock.vue +116 -0
  30. package/components/SLCollapsableMulitPillSelect.vue +92 -0
  31. package/components/SLConfirmModal.vue +122 -0
  32. package/components/SLDateInput.vue +460 -0
  33. package/components/SLDatePicker.vue +143 -0
  34. package/components/SLDistributor.vue +30 -0
  35. package/components/SLDownloadButton.vue +410 -0
  36. package/components/SLDraggable.vue +151 -0
  37. package/components/SLDropdown.vue +277 -0
  38. package/components/SLDropdownItem.vue +31 -0
  39. package/components/SLElementWithTitle.vue +181 -0
  40. package/components/SLEyeCheckbox.vue +162 -0
  41. package/components/SLFileInput.vue +101 -0
  42. package/components/SLGenderAgeSelect.vue +279 -0
  43. package/components/SLHeatMap.vue +151 -0
  44. package/components/SLHourRangeInput.vue +211 -0
  45. package/components/SLIOSSwitch.vue +235 -0
  46. package/components/SLIcon.vue +35 -0
  47. package/components/SLIconButton.vue +130 -0
  48. package/components/SLInfoTip.vue +221 -0
  49. package/components/SLInsightSitePage.vue +27 -0
  50. package/components/SLLegend.vue +76 -0
  51. package/components/SLLinearProgressBar.vue +35 -0
  52. package/components/SLLink.vue +162 -0
  53. package/components/SLLoading.vue +127 -0
  54. package/components/SLMapChart.vue +151 -0
  55. package/components/SLModal.vue +377 -0
  56. package/components/SLMonthCalendarButton.vue +378 -0
  57. package/components/SLMonthPicker.vue +151 -0
  58. package/components/SLMultiSelect.vue +121 -0
  59. package/components/SLNoData.vue +43 -0
  60. package/components/SLPageModal.vue +64 -0
  61. package/components/SLPagination.vue +192 -0
  62. package/components/SLPillCheckbox.vue +207 -0
  63. package/components/SLPillLabel.vue +101 -0
  64. package/components/SLPopupMenuButton.vue +158 -0
  65. package/components/SLProfileButton.vue +186 -0
  66. package/components/SLRadioButton.vue +97 -0
  67. package/components/SLRadioButtonGroup.vue +113 -0
  68. package/components/SLRadioGroup.vue +201 -0
  69. package/components/SLRangeInput.vue +209 -0
  70. package/components/SLRegionsMapChart.vue +151 -0
  71. package/components/SLRightSider.vue +242 -0
  72. package/components/SLSearchInput.vue +87 -0
  73. package/components/SLSelect.vue +545 -0
  74. package/components/SLSelectAllToggle.vue +118 -0
  75. package/components/SLSiderbarNav.vue +394 -0
  76. package/components/SLSiderbarNavItem.vue +204 -0
  77. package/components/SLSitePage.vue +96 -0
  78. package/components/SLSkyInsightSitePage.vue +27 -0
  79. package/components/SLSortByDropdown.vue +189 -0
  80. package/components/SLSpinIcon.vue +24 -0
  81. package/components/SLStayRangeInput.vue +306 -0
  82. package/components/SLTab.vue +159 -0
  83. package/components/SLTable.vue +409 -0
  84. package/components/SLTableTooltip.vue +111 -0
  85. package/components/SLTabs.vue +388 -0
  86. package/components/SLTextInput.vue +362 -0
  87. package/components/SLTextarea.vue +134 -0
  88. package/components/SLToast.vue +71 -0
  89. package/components/SLToggleButton.vue +78 -0
  90. package/components/SLTwoLayerMultiSelect.vue +428 -0
  91. package/components/SLTwoLayerSelect.vue +265 -0
  92. package/components/SLWarnModal.vue +75 -0
  93. package/interface/IDateRange.ts +5 -0
  94. package/interface/IHourRange.ts +4 -0
  95. package/interface/IInputOption.ts +6 -0
  96. package/interface/ILegendItem.ts +7 -0
  97. package/interface/IPopupMenuButton.ts +5 -0
  98. package/interface/IStayRange.ts +15 -0
  99. package/interface/ITableField.ts +19 -0
  100. package/interface/IWeb.ts +5 -0
  101. package/interface/NavConfigType.ts +14 -0
  102. package/interface/commons.ts +7 -0
  103. package/models/DateRange.ts +21 -0
  104. package/nuxt.config.ts +22 -0
  105. package/package.json +52 -0
  106. package/plugins/googlemaps.ts +17 -0
  107. package/plugins/v-calendar.ts +5 -0
  108. package/public/assets/files/taiwan-regions.json +7 -0
  109. package/public/assets/files/taiwan.json +24 -0
  110. package/public/assets/images/commons/default-favico.png +0 -0
  111. package/public/assets/images/dashboard/closure-button-icon.png +0 -0
  112. package/public/assets/images/dashboard/dashboard-widget-bar-chart-icon-disabled.png +0 -0
  113. package/public/assets/images/dashboard/dashboard-widget-bar-chart-icon-poi.png +0 -0
  114. package/public/assets/images/dashboard/dashboard-widget-bar-chart-icon-web.png +0 -0
  115. package/public/assets/images/dashboard/dashboard-widget-country-heatmap-chart-icon-disabled.png +0 -0
  116. package/public/assets/images/dashboard/dashboard-widget-country-heatmap-chart-icon.png +0 -0
  117. package/public/assets/images/dashboard/dashboard-widget-geo-list-icon-disabled.png +0 -0
  118. package/public/assets/images/dashboard/dashboard-widget-geo-list-icon-poi.png +0 -0
  119. package/public/assets/images/dashboard/dashboard-widget-geo-list-icon-web.png +0 -0
  120. package/public/assets/images/dashboard/dashboard-widget-heatmap-chart-icon-disabled.png +0 -0
  121. package/public/assets/images/dashboard/dashboard-widget-heatmap-chart-icon-web.png +0 -0
  122. package/public/assets/images/dashboard/dashboard-widget-line-chart-icon-disabled.png +0 -0
  123. package/public/assets/images/dashboard/dashboard-widget-line-chart-icon-poi.png +0 -0
  124. package/public/assets/images/dashboard/dashboard-widget-list-icon-disabled.png +0 -0
  125. package/public/assets/images/dashboard/dashboard-widget-list-icon-poi.png +0 -0
  126. package/public/assets/images/dashboard/dashboard-widget-list-icon-web.png +0 -0
  127. package/public/assets/images/dashboard/dashboard-widget-pie-chart-icon-disabled.png +0 -0
  128. package/public/assets/images/dashboard/dashboard-widget-pie-chart-icon-poi.png +0 -0
  129. package/public/assets/images/dashboard/dashboard-widget-pie-chart-icon-web.png +0 -0
  130. package/public/assets/images/dashboard/drag-hint-icon.svg +3 -0
  131. package/public/assets/images/dashboard/extend-button-icon.png +0 -0
  132. package/public/assets/images/dashboard/map-list-chart-icon.svg +17 -0
  133. package/public/assets/images/dashboard/map-marker-chart-icon.svg +32 -0
  134. package/public/assets/images/dashboard/pie-chart-icon.svg +4 -0
  135. package/public/assets/images/dashboard/poi-gender-age-chart-icon.svg +20 -0
  136. package/public/assets/images/dashboard/poi-nav-icon.png +0 -0
  137. package/public/assets/images/dashboard/web-gender-age-chart-icon.svg +20 -0
  138. package/public/assets/images/dashboard/web-nav-icon.png +0 -0
  139. package/tailwind.config.js +300 -0
  140. package/tsconfig.json +8 -0
  141. package/utils/constants.ts +160 -0
  142. package/utils/generateSheet.ts +36 -0
  143. package/utils/index.ts +539 -0
@@ -0,0 +1,209 @@
1
+ <template lang="pug">
2
+ .range-input(
3
+ :class="{ inline, disabled, readonly: beReadonly }"
4
+ )
5
+ label(v-if="label") {{ label }}
6
+ .form-control(
7
+ :class="{ 'is-invalid': isInvalid !== null && isInvalid, 'is-valid': isInvalid !== null && !isInvalid }"
8
+ ref="toggle"
9
+ )
10
+ .input-group(
11
+ :class="{ 'is-fill': !!modelValue }"
12
+ )
13
+ .input-range-group
14
+ .range-input-accept-values
15
+ span {{ min }}
16
+ span {{ max }}
17
+ VueSlider(
18
+ v-model='modelValueProxy'
19
+ :min='min'
20
+ :max='max'
21
+ :interval='step'
22
+ :contained='true'
23
+ :lazy='false',
24
+ :disabled='disabled || beReadonly || min === max'
25
+ :dotSize='12'
26
+ :height='6'
27
+ tooltip='none'
28
+ :dotOptions='dotOptions'
29
+ :railStyle='railStyle'
30
+ :processStyle='processStyle'
31
+ )
32
+ input(
33
+ type='text'
34
+ :value='modelValue'
35
+ :disabled='disabled || min === max'
36
+ @input='onInputed'
37
+ @blur='onBlured'
38
+ )
39
+ .invalid-feedback
40
+ slot(name="invalid-feedback") {{ invalidFeedback }}
41
+ </template>
42
+
43
+ <script lang="ts">
44
+ import "vue-slider-component/theme/default.css";
45
+ import VueSlider from "vue-slider-component";
46
+ import type { DotOption } from "vue-slider-component";
47
+
48
+ export default defineComponent({
49
+ name: "SLRangeInput",
50
+ components: { VueSlider },
51
+ props: {
52
+ label: {
53
+ type: String,
54
+ default: undefined,
55
+ },
56
+ inline: {
57
+ type: Boolean,
58
+ default: false,
59
+ },
60
+ modelValue: {
61
+ type: Number,
62
+ default: 0,
63
+ },
64
+ min: {
65
+ type: Number,
66
+ default: 0,
67
+ },
68
+ max: {
69
+ type: Number,
70
+ default: 10,
71
+ },
72
+ step: {
73
+ type: Number,
74
+ default: 1,
75
+ },
76
+ isInvalid: {
77
+ type: Boolean,
78
+ default: false,
79
+ },
80
+ invalidFeedback: {
81
+ type: String,
82
+ default: "",
83
+ },
84
+ disabled: {
85
+ type: Boolean,
86
+ default: false,
87
+ },
88
+ beReadonly: {
89
+ type: Boolean,
90
+ default: false,
91
+ },
92
+ tooltip: {
93
+ type: Boolean,
94
+ default: false,
95
+ },
96
+ },
97
+ emits: ["update:modelValue"],
98
+ setup(props, { emit }) {
99
+ const { modelValue, disabled, beReadonly, min, max } = toRefs(props);
100
+
101
+ const toggle = ref(null);
102
+
103
+ const modelValueProxy = computed({
104
+ get: () => modelValue.value,
105
+ set: (newValue) => {
106
+ emit("update:modelValue", newValue);
107
+ },
108
+ });
109
+ const railStyle = computed(() => ({
110
+ backgroundColor: "#E8EAF2",
111
+ }));
112
+ const dotOptions = computed<DotOption>(() => ({
113
+ disabled: disabled.value || beReadonly.value,
114
+ tooltip: "none",
115
+ style: {
116
+ backgroundColor: "#8486B4",
117
+ borderColor: "#8486B4",
118
+ },
119
+ focusStyle: {
120
+ boxShadow: "none",
121
+ },
122
+ disabledStyle: {
123
+ backgroundColor: "#A09BAF",
124
+ borderColor: "#A09BAF",
125
+ },
126
+ }));
127
+ const processStyle = computed(() => ({
128
+ backgroundColor: "#8486B4",
129
+ }));
130
+ const tooltipStyle = computed(() => ({
131
+ display: "none",
132
+ }));
133
+
134
+ function onInputed(e: Event) {
135
+ const newValue = Number((e.target as HTMLInputElement).value);
136
+
137
+ if (Number.isNaN(newValue) || newValue < min.value) {
138
+ emit("update:modelValue", min.value);
139
+ return;
140
+ } else if (newValue > max.value) {
141
+ emit("update:modelValue", max.value);
142
+ return;
143
+ }
144
+
145
+ emit("update:modelValue", newValue);
146
+ }
147
+
148
+ function onBlured(e: Event) {
149
+ (e.target as HTMLInputElement).value = `${modelValue.value}`;
150
+ }
151
+
152
+ return {
153
+ toggle,
154
+ modelValueProxy,
155
+ railStyle,
156
+ dotOptions,
157
+ processStyle,
158
+ tooltipStyle,
159
+ onInputed,
160
+ onBlured,
161
+ };
162
+ },
163
+ });
164
+ </script>
165
+
166
+ <style lang="stylus">
167
+ .range-input
168
+ &.inline
169
+ @apply flex
170
+
171
+ & > label
172
+ @apply flex-grow-0 flex-shrink-0 mb-0 mr-2 py-2 border-t border-b border-transparent
173
+
174
+ .form-control
175
+ @apply flex-grow
176
+
177
+ &.disabled, &.readonly
178
+ .input-group
179
+ .input-range-group
180
+ .range-input-accept-values
181
+ @apply text-gray-4
182
+
183
+ input[type=text]
184
+ @apply border-primary-light bg-bg
185
+
186
+ & > label
187
+ @apply mb-2 text-base leading-normal text-gray-2
188
+
189
+ .is-invalid
190
+ .invalid-feedback
191
+ @apply block
192
+
193
+
194
+ .input-group
195
+ @apply flex flex-nowrap text-base leading-normal space-x-4
196
+
197
+ .input-range-group
198
+ @apply flex-grow
199
+
200
+ .range-input-accept-values
201
+ @apply flex justify-between mb-1 text-sm text-gray-3
202
+
203
+ input[type=text]
204
+ @apply flex-grow-0 flex-shrink-0 w-11 bg-white border border-primary-light rounded text-base text-center text-gray-2
205
+ @apply s('focus:outline-none')
206
+
207
+ .invalid-feedback
208
+ @apply hidden text-danger text-xs
209
+ </style>
@@ -0,0 +1,151 @@
1
+ <template lang="pug">
2
+ .chart
3
+ ECharts(
4
+ :loading="loading"
5
+ :option="formatedOption"
6
+ autoresize
7
+ @click="onClicked"
8
+ ref="chartComp"
9
+ ).vchart
10
+ </template>
11
+
12
+ <script lang="ts">
13
+ import type { PropType } from "vue";
14
+ import axios from "axios";
15
+ import ECharts from "vue-echarts";
16
+ import { use } from "echarts/core";
17
+ import { registerMap } from "echarts/core";
18
+ import { MapChart } from "echarts/charts";
19
+ import "echarts-wordcloud";
20
+ import {
21
+ GridComponent,
22
+ LegendComponent,
23
+ TooltipComponent,
24
+ VisualMapComponent,
25
+ VisualMapContinuousComponent,
26
+ } from "echarts/components";
27
+ import { CanvasRenderer } from "echarts/renderers";
28
+ import type { ECBasicOption } from "echarts/types/dist/shared";
29
+
30
+ use([
31
+ MapChart,
32
+ GridComponent,
33
+ LegendComponent,
34
+ TooltipComponent,
35
+ VisualMapComponent,
36
+ VisualMapContinuousComponent,
37
+ CanvasRenderer,
38
+ ]);
39
+
40
+ const DefaultGrid = {
41
+ top: 14,
42
+ right: 0,
43
+ bottom: 0,
44
+ left: 30,
45
+ containLabel: true,
46
+ };
47
+
48
+ const DefaultOption = {
49
+ xAxis: {
50
+ axisLine: {
51
+ lineStyle: {
52
+ color: "#828282",
53
+ },
54
+ },
55
+ },
56
+ yAxis: {
57
+ axisLine: {
58
+ show: true,
59
+ lineStyle: {
60
+ color: "#828282",
61
+ },
62
+ },
63
+ axisTick: {
64
+ show: true,
65
+ },
66
+ splitLine: {
67
+ lineStyle: {
68
+ color: "#E5E6F4",
69
+ opacity: 0.5,
70
+ },
71
+ },
72
+ },
73
+ tooltip: {
74
+ padding: 16,
75
+ textStyle: {
76
+ color: "#4F4F4F",
77
+ fontSize: 16,
78
+ lineHeight: 21,
79
+ },
80
+ },
81
+ grid: DefaultGrid,
82
+ };
83
+
84
+ export default defineComponent({
85
+ name: "SLRegionsMapChart",
86
+ components: {
87
+ ECharts,
88
+ },
89
+ props: {
90
+ option: {
91
+ type: Object as PropType<ECBasicOption>,
92
+ default: null,
93
+ },
94
+ loading: {
95
+ type: Boolean,
96
+ default: false,
97
+ },
98
+ },
99
+ emits: ["click"],
100
+ setup(props, { emit }) {
101
+ const { option } = toRefs(props);
102
+
103
+ const mapJsonLoaded = ref(false);
104
+
105
+ const formatedOption = computed(() => {
106
+ if (mapJsonLoaded.value) {
107
+ return {
108
+ ...DefaultOption,
109
+ ...option.value,
110
+ };
111
+ }
112
+
113
+ return {
114
+ ...DefaultOption,
115
+ };
116
+ });
117
+
118
+ function onClicked(e: any) {
119
+ emit("click", e);
120
+ }
121
+
122
+ function loadMapJson() {
123
+ axios
124
+ .get("/assets/files/taiwan-regions.json")
125
+ .then((response) => {
126
+ const { data } = response;
127
+
128
+ registerMap("TaiwanRegions", data);
129
+ mapJsonLoaded.value = true;
130
+ })
131
+ .catch((e) => {
132
+ console.log(e);
133
+ });
134
+ }
135
+
136
+ onMounted(() => {
137
+ loadMapJson();
138
+ });
139
+
140
+ return {
141
+ formatedOption,
142
+ onClicked,
143
+ };
144
+ },
145
+ });
146
+ </script>
147
+
148
+ <style lang="stylus">
149
+ .chart
150
+ @apply h-52
151
+ </style>
@@ -0,0 +1,242 @@
1
+ <template lang="pug">
2
+ .right-sider(:class="{ show: isShow, hover: isHover }" ref="el")
3
+ transition(name="fade")
4
+ .right-sider-modal(
5
+ v-if="isShow"
6
+ @click.prevent="onClickedModal"
7
+ )
8
+ .right-sider-content(:style="`margin-left: -${contentMarginLeft}px; min-height: ${contentMinHeight > 0 ? `${contentMinHeight}px` : 0}`" ref="contentEl")
9
+ SLLink.sider-toggle(
10
+ v-if="icon !== ''"
11
+ :class="`${toggleColor !== '' ? `sider-toggle-${toggleColor}` : ''}`"
12
+ :style="`margin-top: ${78 + order * (44 + 4)}px`"
13
+ :title="toggleTitle"
14
+ @mouseenter="onMouseEnteredToggle"
15
+ @mouseleave="onMouseLeavedToggle"
16
+ @click="toggleSider"
17
+ )
18
+ SLIcon(v-if="icon !== ''" :icon='icon')
19
+ .right-sider-content-wrapper
20
+ slot
21
+ a.sider-close-button(href="javascript:;" @click="toggleSider")
22
+ SLIcon(icon="times")
23
+ .right-sider-addition-content(
24
+ v-show='isShowAdditionContent',
25
+ :style='`margin-right: ${contentMarginLeft + 4}px;`',
26
+ ref='additionContentEl'
27
+ )
28
+ slot(name='addition-content')
29
+ </template>
30
+
31
+ <script lang="ts">
32
+ import { fromEvent, interval, Subscription } from "rxjs";
33
+ import { debounce, startWith } from "rxjs/operators";
34
+
35
+ export default defineComponent({
36
+ name: "SLRightSider",
37
+ components: {},
38
+ props: {
39
+ isShow: {
40
+ type: Boolean,
41
+ default: false,
42
+ },
43
+ isShowAdditionContent: {
44
+ type: Boolean,
45
+ default: false,
46
+ },
47
+ icon: {
48
+ type: String,
49
+ default: "",
50
+ },
51
+ toggleColor: {
52
+ type: String,
53
+ default: "",
54
+ },
55
+ toggleTitle: {
56
+ type: String,
57
+ default: "",
58
+ },
59
+ contentMinHeight: {
60
+ type: Number,
61
+ default: 437,
62
+ },
63
+ closeOnBackdrop: {
64
+ type: Boolean,
65
+ default: false,
66
+ },
67
+ },
68
+ emits: ["update:isShow"],
69
+ setup(props, { emit }) {
70
+ const { isShow, isShowAdditionContent, closeOnBackdrop } = toRefs(props);
71
+
72
+ const el = shallowRef<HTMLElement | null>(null);
73
+ const contentEl = shallowRef<HTMLElement | null>(null);
74
+ const additionContentEl = shallowRef<HTMLElement | null>(null);
75
+ const order = ref(-1);
76
+ const contentMarginLeft = ref(0);
77
+ const isHover = ref(false);
78
+
79
+ let observer: MutationObserver | null = null;
80
+ let resizeSubscriber: Subscription | null = null;
81
+
82
+ function toggleSider() {
83
+ emit("update:isShow", !isShow.value);
84
+ }
85
+
86
+ function caculateCotentMarginLeft() {
87
+ nextTick(() => {
88
+ if (contentEl.value && isShow.value) {
89
+ const contentElRect = contentEl.value.getBoundingClientRect();
90
+ let marginLeft = contentElRect.width;
91
+
92
+ if (isShowAdditionContent.value && additionContentEl.value) {
93
+ const additionContentElRect =
94
+ additionContentEl.value.getBoundingClientRect();
95
+
96
+ const siderFullWidth =
97
+ contentElRect.width + 4 + additionContentElRect.width + 12;
98
+
99
+ if (siderFullWidth > window.innerWidth) {
100
+ marginLeft -= siderFullWidth - window.innerWidth;
101
+ }
102
+ }
103
+
104
+ contentMarginLeft.value = marginLeft;
105
+ return;
106
+ }
107
+
108
+ contentMarginLeft.value = 0;
109
+ });
110
+ }
111
+
112
+ function updateOrder() {
113
+ nextTick(() => {
114
+ const rightSideEl = document.querySelector("#right-side");
115
+ if (!rightSideEl || !el.value) return;
116
+
117
+ const rightSiders = rightSideEl.children;
118
+ let newOrder = -1;
119
+ for (let i = 0; i < rightSiders.length; i += 1) {
120
+ if (rightSiders[i] === el.value) {
121
+ newOrder = i;
122
+ }
123
+ }
124
+
125
+ order.value = newOrder;
126
+ });
127
+ }
128
+
129
+ function onMouseEnteredToggle() {
130
+ isHover.value = true;
131
+ }
132
+
133
+ function onMouseLeavedToggle() {
134
+ isHover.value = false;
135
+ }
136
+
137
+ function subscribeResize() {
138
+ resizeSubscriber = fromEvent(window, "resize")
139
+ .pipe(debounce(() => interval(500)))
140
+ .pipe(startWith(0))
141
+ .subscribe(() => {
142
+ caculateCotentMarginLeft();
143
+ });
144
+ }
145
+
146
+ function unsubscribeResize() {
147
+ if (resizeSubscriber) {
148
+ resizeSubscriber.unsubscribe();
149
+ }
150
+ resizeSubscriber = null;
151
+ }
152
+
153
+ function onClickedModal() {
154
+ if (!closeOnBackdrop.value) return;
155
+
156
+ emit("update:isShow", false);
157
+ }
158
+
159
+ watch([isShow, isShowAdditionContent], () => {
160
+ caculateCotentMarginLeft();
161
+ });
162
+
163
+ onMounted(() => {
164
+ subscribeResize();
165
+
166
+ const rightSideEl = document.querySelector("#right-side");
167
+ if (rightSideEl) {
168
+ observer = new MutationObserver(updateOrder);
169
+ observer.observe(rightSideEl, {
170
+ attributes: false,
171
+ childList: true,
172
+ subtree: false,
173
+ });
174
+ }
175
+ updateOrder();
176
+ });
177
+
178
+ onBeforeUnmount(() => {
179
+ unsubscribeResize();
180
+ if (observer) {
181
+ observer.disconnect();
182
+ }
183
+ observer = null;
184
+ });
185
+
186
+ return {
187
+ el,
188
+ contentEl,
189
+ additionContentEl,
190
+ order,
191
+ contentMarginLeft,
192
+ isHover,
193
+ toggleSider,
194
+ onMouseEnteredToggle,
195
+ onMouseLeavedToggle,
196
+ onClickedModal,
197
+ };
198
+ },
199
+ });
200
+ </script>
201
+
202
+ <style lang="stylus">
203
+ .right-sider
204
+ @apply fixed top-0 right-0 h-full
205
+ z-index 9
206
+
207
+ &.show, &.hover
208
+ @apply z-50
209
+
210
+ &.show
211
+ .right-sider-modal
212
+ @apply block
213
+
214
+ &-modal
215
+ @apply fixed top-0 left-0 w-full h-full s('bg-backdrop/70') hidden
216
+
217
+ &-content
218
+ @apply absolute top-4 left-0 flex p-6 bg-white border-t border-l border-b border-border rounded-l-lg shadow-popup-lg transition-margin
219
+ max-width calc(100vw - 16px)
220
+ max-height calc(100% - theme('spacing.8'))
221
+
222
+ .sider-toggle
223
+ @apply absolute top-0 left-0 inline-flex p-3 rounded-l-full text-lg text-white
224
+ margin-top 78px
225
+ margin-left -44px
226
+
227
+ &-third
228
+ @apply bg-third-hover
229
+
230
+ &-purple
231
+ @apply bg-edit-purple
232
+
233
+ &-wrapper
234
+ @apply flex max-w-full overflow-hidden
235
+
236
+ .sider-close-button
237
+ @apply absolute top-0 right-0 inline-flex mt-6 mr-6 text-base text-primary
238
+
239
+ &-addition-content
240
+ @apply absolute top-4 right-0 flex bg-white border border-border rounded-lg overflow-hidden shadow-popup-lg transition-margin
241
+ max-height calc(100% - theme('spacing.8'))
242
+ </style>
@@ -0,0 +1,87 @@
1
+ <template lang="pug">
2
+ SLTextInput(
3
+ :size='size'
4
+ :modelValue="modelValue"
5
+ :placeholder="placeholder"
6
+ :lazy="lazy"
7
+ @update:modelValue='onInputedValue'
8
+ ).search-input
9
+ template(#append)
10
+ .button-group
11
+ .button-group-divider
12
+ SLButton(v-if="!isSearch", :size='size' @click.prevent="onClickedSearch").btn-search
13
+ SLIcon(icon="search").icon-search
14
+ SLButton(v-else, :size='size' @click.prevent="onClickedClear").btn-clear
15
+ SLIcon(icon="times").icon-times
16
+ </template>
17
+
18
+ <script lang="ts">
19
+ export default defineComponent({
20
+ name: "SLSearchInput",
21
+ components: {},
22
+ props: {
23
+ modelValue: {
24
+ type: String,
25
+ default: "",
26
+ },
27
+ placeholder: {
28
+ type: String,
29
+ default: "",
30
+ },
31
+ lazy: {
32
+ type: [Boolean, Number],
33
+ default: true,
34
+ },
35
+ isSearch: {
36
+ type: Boolean,
37
+ defalut: false,
38
+ },
39
+ size: {
40
+ type: String,
41
+ default: "",
42
+ valiator: (val: string) => ["", "sm"].includes(val),
43
+ },
44
+ },
45
+ emits: ["search", "clear", "update:modelValue", "update:value"],
46
+ setup(_, { emit }) {
47
+ function onClickedSearch(e: Event) {
48
+ emit("search", e);
49
+ }
50
+
51
+ function onClickedClear(e: Event) {
52
+ emit("clear", e);
53
+ }
54
+
55
+ function onInputedValue(newValue: string) {
56
+ emit("update:modelValue", newValue);
57
+ }
58
+
59
+ function onUpdatedValue(newValue: string) {
60
+ emit("update:value", newValue);
61
+ }
62
+
63
+ return {
64
+ onClickedSearch,
65
+ onClickedClear,
66
+ onInputedValue,
67
+ onUpdatedValue,
68
+ };
69
+ },
70
+ });
71
+ </script>
72
+
73
+ <style lang="stylus">
74
+ .search-input
75
+ .is-focus
76
+ .button-group
77
+ @apply border-primary
78
+
79
+ .button-group
80
+ @apply inline-flex items-center h-full s('py-1.25') border-t border-r border-b border-primary-light rounded rounded-l-none bg-white
81
+
82
+ &-divider
83
+ @apply s('w-[0.0625rem]') h-full bg-primary-light
84
+
85
+ .btn
86
+ @apply s('p-0') s('mx-1.75') leading-none text-gray-3 s('focus:outline-none') s('active:outline-none')
87
+ </style>