@opendesign-plus/components 0.0.1-rc.2

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 (60) hide show
  1. package/dist/components/OBanner.vue.d.ts +2 -0
  2. package/dist/components/OCookieNotice.vue.d.ts +16 -0
  3. package/dist/components/OCookieNoticeEl.vue.d.ts +29 -0
  4. package/dist/components/OHeaderSearch.vue.d.ts +692 -0
  5. package/dist/components/OPlusConfigProvider.vue.d.ts +23 -0
  6. package/dist/components/OSection.vue.d.ts +37 -0
  7. package/dist/components/OThemeSwitcher.vue.d.ts +28 -0
  8. package/dist/components.cjs.js +1 -0
  9. package/dist/components.css +1 -0
  10. package/dist/components.es.js +1206 -0
  11. package/dist/components.umd.js +1 -0
  12. package/dist/index.d.ts +12 -0
  13. package/docs/design.md +27 -0
  14. package/docs/design_banner.md +41 -0
  15. package/docs/design_section.md +27 -0
  16. package/package.json +47 -0
  17. package/scripts/generate-components-index.js +81 -0
  18. package/src/assets/svg-icons/icon-chevron-right.svg +3 -0
  19. package/src/assets/svg-icons/icon-close.svg +3 -0
  20. package/src/assets/svg-icons/icon-delete.svg +3 -0
  21. package/src/assets/svg-icons/icon-header-back.svg +3 -0
  22. package/src/assets/svg-icons/icon-header-delete.svg +3 -0
  23. package/src/assets/svg-icons/icon-header-search.svg +4 -0
  24. package/src/assets/svg-icons/icon-moon.svg +3 -0
  25. package/src/assets/svg-icons/icon-sun.svg +3 -0
  26. package/src/components/OBanner.vue +390 -0
  27. package/src/components/OCookieNotice.vue +424 -0
  28. package/src/components/OCookieNoticeEl.vue +404 -0
  29. package/src/components/OHeaderSearch.vue +601 -0
  30. package/src/components/OPlusConfigProvider.vue +32 -0
  31. package/src/components/OSection.vue +178 -0
  32. package/src/components/OThemeSwitcher.vue +108 -0
  33. package/src/components/common/ClientOnlyWrapper.ts +21 -0
  34. package/src/components/common/ContentWrapper.vue +85 -0
  35. package/src/draft/Banner.vue +265 -0
  36. package/src/draft/ButtonCards.vue +106 -0
  37. package/src/draft/Feature.vue +134 -0
  38. package/src/draft/Footer.vue +512 -0
  39. package/src/draft/HorizontalAnchor.vue +165 -0
  40. package/src/draft/ItemSwiper.vue +133 -0
  41. package/src/draft/Logo.vue +141 -0
  42. package/src/draft/LogoCard.vue +75 -0
  43. package/src/draft/LogoV2.vue +19 -0
  44. package/src/draft/MainCard.vue +38 -0
  45. package/src/draft/MultiCard.vue +95 -0
  46. package/src/draft/MultiIconCard.vue +74 -0
  47. package/src/draft/OInfoCard.vue +176 -0
  48. package/src/draft/Process.vue +81 -0
  49. package/src/draft/Section.vue +167 -0
  50. package/src/draft/SingleTabCard.vue +85 -0
  51. package/src/draft/SliderCard.vue +110 -0
  52. package/src/env.d.ts +1 -0
  53. package/src/i18n/en.ts +20 -0
  54. package/src/i18n/index.ts +42 -0
  55. package/src/i18n/zh.ts +9 -0
  56. package/src/index.ts +34 -0
  57. package/src/shared/provide.ts +6 -0
  58. package/src/vue.d.ts +10 -0
  59. package/tsconfig.json +33 -0
  60. package/vite.config.ts +94 -0
@@ -0,0 +1,424 @@
1
+ <script lang="ts" setup>
2
+ import { ref, onMounted, computed, nextTick, watch } from 'vue';
3
+ import ClientOnly from './common/ClientOnlyWrapper';
4
+ import { useScreen } from '@opendesign-plus/composables';
5
+ import { useI18n } from '@/i18n';
6
+ import { DialogActionT, OButton, ODialog, OIcon, OIconClose, OSwitch } from '@opensig/opendesign';
7
+ import { useVModel } from '@vueuse/core';
8
+
9
+ const NOT_SIGNED = '0';
10
+ const ALL_AGREED = '1';
11
+ const NECCESSARY_AGREED = '2';
12
+ const NOT_SHOW_BUT_AGREED = '3';
13
+ const COOKIE_DOMAIN = import.meta.env.VITE_COOKIE_DOMAIN as string;
14
+ const COOKIE_KEY_ZH = 'agreed-cookiepolicy-zh';
15
+ const COOKIE_KEY_EN = 'agreed-cookiepolicy-en';
16
+
17
+ const props = defineProps<{
18
+ visible?: boolean;
19
+ enableGrid?: boolean;
20
+ community: string;
21
+ aboutPathZh: string;
22
+ aboutPathEn: string;
23
+ teleportTarget?: string | HTMLElement;
24
+ }>();
25
+
26
+ const emit = defineEmits<{
27
+ (e: 'update:visible', value: boolean): void;
28
+ }>();
29
+
30
+ const { lePadV, leLaptop } = useScreen();
31
+ const { locale, t } = useI18n();
32
+ const isZh = computed(() => locale.value === 'zh');
33
+
34
+ const cookieKey = computed(() => (isZh.value ? COOKIE_KEY_ZH : COOKIE_KEY_EN));
35
+
36
+ // 是否允许分析cookie
37
+ const analysisAllowed = ref(false);
38
+ const visibleVmodel = useVModel(props, 'visible', emit, { defaultValue: false });
39
+
40
+ const getCookie = (key: string) => {
41
+ const cookie = document.cookie.split(';').find((row) => row.split('=')[0].trim() === encodeURIComponent(key));
42
+ if (!cookie) {
43
+ return null;
44
+ }
45
+ return decodeURIComponent(cookie.split('=')[1]);
46
+ };
47
+
48
+ const setCookie = (key: string, value: string, days: number, domain: string) => {
49
+ const maxAge = days ? `; max-age=${days * 24 * 60 * 60}` : '';
50
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}${maxAge}; path=/; domain=${domain}`;
51
+ };
52
+
53
+ const removeCookie = (key: string, domain: string) => {
54
+ document.cookie = `${encodeURIComponent(key)}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${domain}`;
55
+ };
56
+
57
+ // 显示/隐藏cookie提示
58
+ const toggleNoticeVisible = (val?: boolean) => {
59
+ if (typeof val === 'boolean') {
60
+ visibleVmodel.value = val;
61
+ } else {
62
+ visibleVmodel.value = !visibleVmodel.value;
63
+ }
64
+ nextTick(() => {
65
+ if (!visibleVmodel.value && isZh.value && getCookie(cookieKey.value) !== NOT_SHOW_BUT_AGREED) {
66
+ setCookie(cookieKey.value, NOT_SHOW_BUT_AGREED, 180, COOKIE_DOMAIN ?? location.hostname);
67
+ }
68
+ });
69
+ };
70
+
71
+ // 弹出框是否显示
72
+ const isDlgVisible = ref(false);
73
+
74
+ // 显示/隐藏弹出框
75
+ const toggleDlgVisible = (val?: boolean) => {
76
+ if (typeof val === 'boolean') {
77
+ isDlgVisible.value = val;
78
+ } else {
79
+ isDlgVisible.value = !isDlgVisible.value;
80
+ }
81
+ };
82
+
83
+ // 是否未签署
84
+ const isNotSigned = () => {
85
+ if (isZh.value) {
86
+ return getCookie(cookieKey.value) !== NOT_SHOW_BUT_AGREED;
87
+ }
88
+ return (getCookie(cookieKey.value) ?? '0') === NOT_SIGNED;
89
+ };
90
+
91
+ // 是否全部同意
92
+ const isAllAgreed = () => {
93
+ if (isZh.value) {
94
+ return getCookie(cookieKey.value) === NOT_SHOW_BUT_AGREED;
95
+ }
96
+ return getCookie(cookieKey.value) === ALL_AGREED;
97
+ };
98
+
99
+ onMounted(() => {
100
+ // 未签署,展示cookie notice
101
+ if (isNotSigned()) {
102
+ toggleNoticeVisible(true);
103
+ }
104
+ });
105
+
106
+ watch(locale, () => {
107
+ toggleNoticeVisible(isNotSigned());
108
+ });
109
+
110
+ // 用户同意所有cookie
111
+ const acceptAll = () => {
112
+ analysisAllowed.value = true;
113
+ removeCookie(cookieKey.value, COOKIE_DOMAIN ?? location.hostname);
114
+ setCookie(cookieKey.value, ALL_AGREED, 180, COOKIE_DOMAIN ?? location.hostname);
115
+ toggleNoticeVisible(false);
116
+ };
117
+
118
+ // 用户拒绝所有cookie,即仅同意必要cookie
119
+ const rejectAll = () => {
120
+ analysisAllowed.value = false;
121
+ removeCookie(cookieKey.value, COOKIE_DOMAIN ?? location.hostname);
122
+ setCookie(cookieKey.value, NECCESSARY_AGREED, 180, COOKIE_DOMAIN ?? location.hostname);
123
+ toggleNoticeVisible(false);
124
+ };
125
+
126
+ // 弹出框设置
127
+ const dlgActions = computed<Array<DialogActionT>>(() => [
128
+ {
129
+ id: 'save',
130
+ color: 'primary',
131
+ label: t('cookie.saveSetting'),
132
+ variant: 'outline',
133
+ size: 'large',
134
+ round: 'pill',
135
+ onClick: () => {
136
+ if (analysisAllowed.value) {
137
+ acceptAll();
138
+ } else {
139
+ rejectAll();
140
+ }
141
+
142
+ toggleDlgVisible(false);
143
+ },
144
+ },
145
+ {
146
+ id: 'allowAll',
147
+ color: 'primary',
148
+ label: t('cookie.acceptAll'),
149
+ variant: 'outline',
150
+ size: 'large',
151
+ round: 'pill',
152
+ onClick: () => {
153
+ analysisAllowed.value = true;
154
+ acceptAll();
155
+ toggleDlgVisible(false);
156
+ },
157
+ },
158
+ ]);
159
+
160
+ const onDlgChange = (val: boolean) => {
161
+ if (val) {
162
+ analysisAllowed.value = isAllAgreed();
163
+ }
164
+ };
165
+
166
+ defineExpose({
167
+ check() {
168
+ const agreed = isAllAgreed();
169
+ if (agreed === visibleVmodel.value) {
170
+ toggleNoticeVisible();
171
+ }
172
+ },
173
+ });
174
+ </script>
175
+
176
+ <template>
177
+ <ClientOnly>
178
+ <Teleport :to="teleportTarget || '#app'">
179
+ <div v-if="visibleVmodel" class="cookie-notice">
180
+ <div class="cookie-notice-content">
181
+ <div :type="locale" :class="{ 'cookie-notice-wrap-grid': enableGrid, 'cookie-notice-wrap': !enableGrid }">
182
+ <div class="cookie-notice-left">
183
+ <p v-if="isZh" class="cookie-desc" style="margin-top: 0">
184
+ {{ t('cookie.desc') }}
185
+ <a :href="aboutPathZh" target="_blank" rel="noopener noreferrer">
186
+ {{ t('cookie.about') }}
187
+ </a>
188
+ </p>
189
+ <template v-else>
190
+ <p class="cookie-title">{{ t('cookie.title', [community]) }}</p>
191
+ <p class="cookie-desc">
192
+ {{ t('cookie.desc') }}
193
+ <a :href="aboutPathEn" target="_blank" rel="noopener noreferrer">{{ t('cookie.about') }} </a>.
194
+ </p>
195
+ </template>
196
+ </div>
197
+ <div v-if="!isZh" class="cookie-notice-right">
198
+ <OButton round="pill" variant="outline" color="primary" @click="acceptAll">{{ t('cookie.acceptAll') }}</OButton>
199
+ <OButton round="pill" variant="outline" color="primary" @click="rejectAll">{{ t('cookie.rejectAll') }}</OButton>
200
+ <OButton round="pill" variant="outline" color="primary" @click="toggleDlgVisible(true)">
201
+ {{ t('cookie.manage') }}
202
+ </OButton>
203
+ </div>
204
+ <OIcon class="cookie-notice-close" :type="locale" @click="toggleNoticeVisible(false)">
205
+ <OIconClose />
206
+ </OIcon>
207
+ </div>
208
+ </div>
209
+ <ODialog
210
+ v-model:visible="isDlgVisible"
211
+ :size="leLaptop ? 'medium' : 'large'"
212
+ :phone-half-full="lePadV"
213
+ class="cookie-dlg"
214
+ :actions="dlgActions"
215
+ @change="onDlgChange"
216
+ >
217
+ <template #header>
218
+ <span class="cookie-dlg-title">{{ t('cookie.manage') }}</span>
219
+ </template>
220
+ <div class="cookie-dlg-content">
221
+ <div class="content-item">
222
+ <div class="item-header">
223
+ <span class="item-title">{{ t('cookie.necessaryCookie') }}</span>
224
+ <span class="item-extra">{{ t('cookie.alwaysOn') }}</span>
225
+ </div>
226
+ <div class="item-detail">
227
+ {{ t('cookie.necessaryCookieDetail') }}
228
+ </div>
229
+ </div>
230
+ <div class="content-item">
231
+ <div class="item-header">
232
+ <span class="item-title">{{ t('cookie.analyticalCookie') }}</span>
233
+ <span class="item-extra">
234
+ <OSwitch v-model="analysisAllowed" />
235
+ </span>
236
+ </div>
237
+ <div class="item-detail">
238
+ {{ t('cookie.analyticalCookieDetail') }}
239
+ </div>
240
+ </div>
241
+ </div>
242
+ </ODialog>
243
+ </div>
244
+ </Teleport>
245
+ </ClientOnly>
246
+ </template>
247
+
248
+ <style lang="scss" scoped>
249
+ .cookie-notice {
250
+ position: fixed;
251
+ bottom: 0;
252
+ z-index: 999;
253
+ width: 100%;
254
+ .o-button {
255
+ --o-button-font-size-mini: 14px;
256
+ }
257
+ .o-button + .o-button {
258
+ margin-left: 16px;
259
+
260
+ @media (max-width: 840px) {
261
+ margin-left: 0;
262
+ margin-top: 12px;
263
+ }
264
+ }
265
+ }
266
+
267
+ .cookie-notice-content {
268
+ background-color: rgba(var(--o-mixedgray-1), 0.9);
269
+ backdrop-filter: blur(5px);
270
+ box-shadow: var(--o-shadow-1);
271
+ }
272
+
273
+ .cookie-notice-wrap {
274
+ position: relative;
275
+ display: flex;
276
+ justify-content: space-between;
277
+ margin: 0 auto;
278
+ padding: 24px var(--layout-content-padding);
279
+ max-width: var(--layout-content-max-width);
280
+ &:not([type='zh']) {
281
+ @media (max-width: 840px) {
282
+ flex-direction: column;
283
+ align-items: center;
284
+ }
285
+ }
286
+ }
287
+
288
+ .cookie-notice-wrap-grid {
289
+ position: relative;
290
+ display: flex;
291
+ justify-content: space-between;
292
+ width: var(--grid-content-width);
293
+ padding: 24px 0;
294
+ margin: 0 auto;
295
+ &:not([type='zh']) {
296
+ @media (max-width: 840px) {
297
+ padding: 16px 0;
298
+ flex-direction: column;
299
+ align-items: center;
300
+ }
301
+ }
302
+ }
303
+
304
+ .cookie-notice-left {
305
+ width: 60%;
306
+
307
+ @media (max-width: 1100px) {
308
+ width: 58%;
309
+ }
310
+
311
+ @media (max-width: 840px) {
312
+ width: 100%;
313
+ }
314
+
315
+ .cookie-title {
316
+ font-size: 16px;
317
+ line-height: 28px;
318
+ color: var(--o-color-info1);
319
+ font-weight: 500;
320
+ @media (max-width: 840px) {
321
+ font-size: 16px;
322
+ line-height: 24px;
323
+ text-align: center;
324
+ }
325
+ }
326
+
327
+ .cookie-desc {
328
+ font-size: 12px;
329
+ line-height: 18px;
330
+ color: var(--o-color-info2);
331
+ margin-top: 8px;
332
+ }
333
+ }
334
+
335
+ .cookie-notice-right {
336
+ display: flex;
337
+ align-items: center;
338
+ margin-top: 12px;
339
+
340
+ @media (max-width: 840px) {
341
+ width: 100%;
342
+ }
343
+
344
+ @media (max-width: 840px) {
345
+ flex-direction: column;
346
+ align-items: center;
347
+ }
348
+
349
+ .o-btn:not(:first-child) {
350
+ margin-left: 16px;
351
+ }
352
+
353
+ @media (max-width: 840px) {
354
+ .o-btn {
355
+ align-self: stretch;
356
+ &:not(:first-child) {
357
+ margin-top: 12px;
358
+ margin-left: 0;
359
+ }
360
+ }
361
+ }
362
+ }
363
+
364
+ .cookie-notice-close {
365
+ &[type='en'] {
366
+ position: absolute;
367
+ top: 16px;
368
+ right: var(--layout-content-padding);
369
+ transform-origin: center;
370
+ }
371
+ cursor: pointer;
372
+ color: var(--o-color-info1);
373
+ font-size: 20px;
374
+ &:hover {
375
+ color: var(--o-color-primary2);
376
+ }
377
+ @media (max-width: 840px) {
378
+ font-size: 14px;
379
+ }
380
+ @include x-svg-hover;
381
+ }
382
+
383
+ .cookie-notice-wrap-grid .cookie-notice-close {
384
+ right: 0;
385
+ }
386
+
387
+ .cookie-dlg-content {
388
+ .content-item + .content-item {
389
+ margin-top: 24px;
390
+ }
391
+
392
+ .content-item {
393
+ .item-header {
394
+ display: flex;
395
+ align-items: center;
396
+ .item-title {
397
+ font-size: 18px;
398
+ line-height: 32px;
399
+ color: var(--o-color-info1);
400
+ font-weight: 500;
401
+ }
402
+
403
+ .item-extra {
404
+ font-size: 14px;
405
+ line-height: 22px;
406
+ color: var(--o-color-info3);
407
+ margin-left: 24px;
408
+ }
409
+ }
410
+
411
+ .item-detail {
412
+ font-size: 16px;
413
+ line-height: 28px;
414
+ color: var(--o-color-info2);
415
+ margin-top: 12px;
416
+ @media (max-width: 840px) {
417
+ font-size: 14px;
418
+ line-height: 21px;
419
+ margin-top: 8px;
420
+ }
421
+ }
422
+ }
423
+ }
424
+ </style>