@solar-taro/ui-sun 0.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 (56) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/README.md +11 -0
  3. package/eslint.config.cjs +22 -0
  4. package/package.json +17 -0
  5. package/project.json +28 -0
  6. package/shims-vue.d.ts +5 -0
  7. package/src/_color.scss +41 -0
  8. package/src/_sun.scss +15 -0
  9. package/src/_wx.scss +23 -0
  10. package/src/accordion/index.scss +18 -0
  11. package/src/accordion/index.ts +1 -0
  12. package/src/accordion/index.vue +27 -0
  13. package/src/chip/index.scss +77 -0
  14. package/src/chip/index.ts +1 -0
  15. package/src/chip/index.vue +27 -0
  16. package/src/fab/fab-group.vue +17 -0
  17. package/src/fab/fab.vue +5 -0
  18. package/src/fab/index.scss +18 -0
  19. package/src/fab/index.ts +2 -0
  20. package/src/index.scss +3 -0
  21. package/src/index.ts +11 -0
  22. package/src/lazy-render/index.ts +1 -0
  23. package/src/lazy-render/index.vue +38 -0
  24. package/src/navbar/index.scss +18 -0
  25. package/src/navbar/index.ts +1 -0
  26. package/src/navbar/index.vue +26 -0
  27. package/src/popover/index.scss +100 -0
  28. package/src/popover/index.ts +1 -0
  29. package/src/popover/index.vue +56 -0
  30. package/src/segment/index.scss +44 -0
  31. package/src/segment/index.ts +2 -0
  32. package/src/segment/injection.ts +8 -0
  33. package/src/segment/segment-btn.vue +28 -0
  34. package/src/segment/segment.vue +86 -0
  35. package/src/spinner/index.scss +84 -0
  36. package/src/spinner/index.ts +1 -0
  37. package/src/spinner/index.vue +26 -0
  38. package/src/sudoku/index.scss +22 -0
  39. package/src/sudoku/index.ts +2 -0
  40. package/src/sudoku/sudoku-item.vue +5 -0
  41. package/src/sudoku/sudoku.vue +23 -0
  42. package/src/table/_table-cell.scss +50 -0
  43. package/src/table/_table-row.scss +14 -0
  44. package/src/table/_table.scss +70 -0
  45. package/src/table/index.scss +3 -0
  46. package/src/table/index.ts +3 -0
  47. package/src/table/table-cell.vue +26 -0
  48. package/src/table/table-row.vue +12 -0
  49. package/src/table/table.vue +39 -0
  50. package/src/virtual-scroll/index.scss +17 -0
  51. package/src/virtual-scroll/index.ts +1 -0
  52. package/src/virtual-scroll/index.vue +138 -0
  53. package/tsconfig.json +21 -0
  54. package/tsconfig.lib.json +26 -0
  55. package/tsconfig.spec.json +28 -0
  56. package/vite.config.ts +130 -0
@@ -0,0 +1,44 @@
1
+ .sun-segment {
2
+ --border-radius: 14rpx;
3
+ --segment-background: rgba(0, 0, 0, 0.03);
4
+ height: 100%;
5
+ font-size: 26rpx;
6
+ border-radius: calc(var(--border-radius) + 1.5px);
7
+ background: var(--segment-background);
8
+ overflow: hidden;
9
+
10
+ &-inner {
11
+ position: relative;
12
+ display: flex;
13
+ margin: 2.5px;
14
+ height: calc(100% - 5px);
15
+
16
+ &::after {
17
+ content: "";
18
+ position: absolute;
19
+ top: 0;
20
+ left: 0;
21
+ height: 100%;
22
+ width: calc(100% / var(--segment-length));
23
+ background: var(--color-white);
24
+ border-radius: var(--border-radius);
25
+ box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.1);
26
+ transition: transform 260ms cubic-bezier(0.4, 0, 0.2, 1);
27
+ transform: translateX(calc(100% * var(--segment-active-index)));
28
+ }
29
+ }
30
+
31
+ &-btn {
32
+ position: relative;
33
+ display: flex;
34
+ justify-content: center;
35
+ align-items: center;
36
+ flex: 1;
37
+ height: 28px;
38
+ z-index: 1;
39
+
40
+ &-active {
41
+ font-weight: 500;
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,2 @@
1
+ export { default as SunSegmentBtn } from './segment-btn.vue';
2
+ export { default as SunSegment } from './segment.vue';
@@ -0,0 +1,8 @@
1
+ import { ComponentInternalInstance, InjectionKey, Ref } from 'vue';
2
+
3
+ export const ACTIVE_CHILD = Symbol() as InjectionKey<Ref<ComponentInternalInstance>>;
4
+ export const PARENT = Symbol() as InjectionKey<{
5
+ link(child: ComponentInternalInstance): void;
6
+ unlink(child: ComponentInternalInstance): void;
7
+ active(child: ComponentInternalInstance): void;
8
+ }>;
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <view
3
+ v-bind="$attrs"
4
+ class="sun-segment-btn"
5
+ :class="{ 'sun-segment-btn-active': activeChild?.props['value'] === value }"
6
+ @tap="parent.active(instance)">
7
+ <slot></slot>
8
+ </view>
9
+ </template>
10
+
11
+ <script lang="ts" setup>
12
+ import { getCurrentInstance, inject, onUnmounted } from 'vue';
13
+ import { ACTIVE_CHILD, PARENT } from './injection';
14
+
15
+ defineProps<{
16
+ value: unknown
17
+ }>();
18
+
19
+ const activeChild = inject(ACTIVE_CHILD)!;
20
+ const parent = inject(PARENT)!;
21
+ const instance = getCurrentInstance()!;
22
+
23
+ onUnmounted(() => {
24
+ parent.unlink(instance);
25
+ });
26
+
27
+ parent.link(instance);
28
+ </script>
@@ -0,0 +1,86 @@
1
+ <template>
2
+ <view v-bind="$attrs" class="sun-segment" :style="style">
3
+ <view class="sun-segment-inner">
4
+ <slot></slot>
5
+ </view>
6
+ </view>
7
+ </template>
8
+
9
+ <script lang="ts" setup>
10
+ import { ComponentInternalInstance, computed, getCurrentInstance, onMounted, provide, shallowReactive, shallowRef, VNode, watch } from 'vue';
11
+ import { ACTIVE_CHILD, PARENT } from './injection';
12
+
13
+ const emit = defineEmits<{
14
+ (e: 'update:modelValue', v: unknown): void;
15
+ (e: 'change', v: { value: unknown, index: number }): void;
16
+ }>();
17
+
18
+ const props = defineProps<{
19
+ modelValue: unknown
20
+ }>();
21
+
22
+ const instance = getCurrentInstance()!;
23
+
24
+ const activeChild = shallowRef(null as unknown as ComponentInternalInstance);
25
+ const children = shallowReactive<ComponentInternalInstance[]>([]);
26
+
27
+ const activeIndex = computed(() => children.indexOf(activeChild.value));
28
+ const childrenLength = computed(() => children.length);
29
+ const style = computed(() => ({
30
+ '--segment-length': childrenLength.value,
31
+ '--segment-active-index': activeIndex.value
32
+ }))
33
+
34
+ provide(ACTIVE_CHILD, activeChild);
35
+ provide(PARENT, {
36
+ link: (child: ComponentInternalInstance) => {
37
+ const vnodes = getChildVnodes();
38
+
39
+ children.push(child);
40
+ children.sort((a, b) => {
41
+ const indexA = vnodes.indexOf(a.vnode);
42
+ const indexB = vnodes.indexOf(b.vnode);
43
+ return indexA - indexB;
44
+ });
45
+ },
46
+ unlink: (child: ComponentInternalInstance) => {
47
+ children.slice(children.indexOf(child), 1);
48
+ },
49
+ active: (child: ComponentInternalInstance) => {
50
+ emit('change', {
51
+ value: child.props['value'],
52
+ index: activeIndex.value
53
+ });
54
+ emit('update:modelValue', child.props['value']);
55
+ activeChild.value = child;
56
+ }
57
+ });
58
+
59
+ watch(() => props.modelValue, value => {
60
+ activeChild.value = children.find(o => o.props['value'] === value)!;
61
+ });
62
+
63
+ function getChildVnodes(): VNode[] {
64
+ // @ts-ignore
65
+ return instance
66
+ .subTree
67
+ .children[0]
68
+ .children[0]
69
+ .children
70
+ .filter((vnode: VNode) => typeof vnode.type !== 'symbol');
71
+ }
72
+
73
+ onMounted(() => {
74
+ const vnodes = getChildVnodes();
75
+
76
+ children.forEach(child => {
77
+ const index = vnodes.findIndex(o => o === child.vnode);
78
+
79
+ child.props['value'] ??= index;
80
+
81
+ if (child.props['value'] === props.modelValue) {
82
+ activeChild.value = child;
83
+ }
84
+ });
85
+ });
86
+ </script>
@@ -0,0 +1,84 @@
1
+ .sun-spinner {
2
+ --spinner-color: var(--color-primary);
3
+ --spinner-dot-size: 26rpx;
4
+ --spinner-dot-gap: 10rpx;
5
+ --spinner-desc-size: 26rpx;
6
+ display: inline-block;
7
+
8
+ &-small {
9
+ --spinner-dot-size: 14rpx;
10
+ --spinner-dot-gap: 4rpx;
11
+ --spinner-desc-size: 22rpx;
12
+ }
13
+
14
+ &-middle {
15
+ --spinner-dot-size: 20rpx;
16
+ --spinner-dot-gap: 6rpx;
17
+ --spinner-desc-size: 24rpx;
18
+ }
19
+
20
+ &-large {
21
+ --spinner-dot-size: 36rpx;
22
+ --spinner-dot-gap: 14rpx;
23
+ --spinner-desc-size: 28rpx;
24
+ }
25
+
26
+ &-spinning > &-dot {
27
+ animation: sun-spinner-rotate 1.2s infinite linear;
28
+ }
29
+
30
+ &-dot {
31
+ display: inline-flex;
32
+ flex-wrap: wrap;
33
+ width: calc(var(--spinner-dot-size) * 2 + var(--spinner-dot-gap) * 4);
34
+
35
+ &-item {
36
+ height: var(--spinner-dot-size);
37
+ width: var(--spinner-dot-size);
38
+ margin: var(--spinner-dot-gap);
39
+ border-radius: 50%;
40
+ background: var(--spinner-color);
41
+ opacity: 0.25;
42
+ animation: sun-spinner-breath 0.8s infinite linear alternate;
43
+
44
+ &:nth-child(2) {
45
+ animation-delay: 0.4s;
46
+ }
47
+
48
+ &:nth-child(3) {
49
+ animation-delay: 0.8s;
50
+ }
51
+
52
+ &:nth-child(4) {
53
+ animation-delay: 1.2s;
54
+ }
55
+ }
56
+ }
57
+
58
+ &-desc {
59
+ text-align: center;
60
+ font-size: var(--spinner-desc-size);
61
+ color: var(--spinner-color);
62
+ margin-top: 12rpx;
63
+ }
64
+ }
65
+
66
+ @keyframes sun-spinner-rotate {
67
+ from {
68
+ transform: rotate(0);
69
+ }
70
+
71
+ to {
72
+ transform: rotate(360deg);
73
+ }
74
+ }
75
+
76
+ @keyframes sun-spinner-breath {
77
+ from {
78
+ opacity: 0.25;
79
+ }
80
+
81
+ to {
82
+ opacity: 1;
83
+ }
84
+ }
@@ -0,0 +1 @@
1
+ export { default as SunSpinner } from './index.vue';
@@ -0,0 +1,26 @@
1
+ <template>
2
+ <view class="sun-spinner" :class="className">
3
+ <view class="sun-spinner-dot">
4
+ <view v-for="o of 4" :key="o" class="sun-spinner-dot-item"></view>
5
+ </view>
6
+ <view v-if="$slots['default']" class="sun-spinner-desc">
7
+ <slot></slot>
8
+ </view>
9
+ </view>
10
+ </template>
11
+
12
+ <script lang="ts" setup>
13
+ import { computed } from 'vue';
14
+
15
+ const props = defineProps<{
16
+ size?: 'small' | 'middle' | 'default' | 'large';
17
+ spinning?: boolean;
18
+ }>();
19
+
20
+ const className = computed(() => [
21
+ {
22
+ 'sun-spinner-spinning': props.spinning,
23
+ },
24
+ `sun-spinner-${props.size}`
25
+ ]);
26
+ </script>
@@ -0,0 +1,22 @@
1
+ .sun-sudoku {
2
+ display: flex;
3
+ flex-wrap: wrap;
4
+ width: var(--sudoku-width);
5
+
6
+ &-item {
7
+ width: var(--sudoku-item-size);
8
+ height: var(--sudoku-item-size);
9
+ }
10
+
11
+ &-lg {
12
+ --sudoku-item-size: calc(var(--sudoku-width) / 3);
13
+ }
14
+
15
+ &-md {
16
+ --sudoku-item-size: calc(var(--sudoku-width) / 2);
17
+ }
18
+
19
+ &-sm {
20
+ --sudoku-item-size: var(--sudoku-width);
21
+ }
22
+ }
@@ -0,0 +1,2 @@
1
+ export { default as SunSudokuItem } from './sudoku-item.vue';
2
+ export { default as SunSudoku } from './sudoku.vue';
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <view v-bind="$attrs" class="sun-sudoku-item">
3
+ <slot></slot>
4
+ </view>
5
+ </template>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <view v-bind="$attrs" class="sun-sudoku" :class="classes" :style="{ '--sudoku-width': size }">
3
+ <slot></slot>
4
+ </view>
5
+ </template>
6
+
7
+ <script lang="ts" setup>
8
+ import { computed } from 'vue';
9
+
10
+ const props = defineProps({
11
+ size: String,
12
+ count: {
13
+ type: Number,
14
+ default: 9
15
+ }
16
+ });
17
+
18
+ const classes = computed(() => ({
19
+ 'sun-sudoku-sm': props.count === 1,
20
+ 'sun-sudoku-md': props.count === 2 || props.count === 4,
21
+ 'sun-sudoku-lg': props.count === 3 || props.count > 4,
22
+ }))
23
+ </script>
@@ -0,0 +1,50 @@
1
+ .sun-tb-cell {
2
+ display: table-cell;
3
+ background: var(--color-white);
4
+ vertical-align: middle;
5
+ white-space: nowrap;
6
+
7
+ &-break-word {
8
+ white-space: normal;
9
+ word-break: break-all;
10
+ }
11
+
12
+ &-ellipsis {
13
+ text-overflow: ellipsis;
14
+ overflow: hidden;
15
+ white-space: nowrap;
16
+ }
17
+
18
+ &-sticky-left,
19
+ &-sticky-right {
20
+ position: -webkit-sticky;
21
+ position: sticky;
22
+ background: var(--color-white);
23
+
24
+ &::after {
25
+ position: absolute;
26
+ top: 0;
27
+ content: "";
28
+ height: 100%;
29
+ width: 7.5rpx;
30
+ }
31
+ }
32
+
33
+ &-sticky-left {
34
+ left: 0;
35
+
36
+ &::after {
37
+ left: 100%;
38
+ background: linear-gradient(to right, rgba(#000, 0.05), transparent);
39
+ }
40
+ }
41
+
42
+ &-sticky-right {
43
+ right: 0;
44
+
45
+ &::after {
46
+ right: 100%;
47
+ background: linear-gradient(to left, rgba(#000, 0.05), transparent);
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,14 @@
1
+ .sun-tb {
2
+ &-row {
3
+ display: table-row;
4
+
5
+ &:not(:last-child) > .sun-tb-cell {
6
+ border-bottom: 0.5px solid var(--border-color);
7
+ }
8
+ }
9
+
10
+ &-head,
11
+ &-foot {
12
+ font-weight: bold;
13
+ }
14
+ }
@@ -0,0 +1,70 @@
1
+ .sun-tb {
2
+ --border-color: #e2e8f0;
3
+
4
+ overflow: auto;
5
+ border-collapse: collapse;
6
+ -webkit-overflow-scrolling: touch;
7
+
8
+ &::-webkit-scrollbar {
9
+ display: none;
10
+ }
11
+
12
+ &-rounded {
13
+ border-radius: 12rpx;
14
+ }
15
+
16
+ &-bordered {
17
+ border: 0.5px solid var(--border-color);
18
+
19
+ .sun-tb-cell {
20
+ border: 0.5px solid var(--border-color);
21
+ }
22
+ }
23
+
24
+ &-outer-bordered {
25
+ border: 0.5px solid var(--border-color);
26
+ }
27
+ }
28
+
29
+ // table
30
+ .sun-tb-inner {
31
+ display: table;
32
+ width: 100%;
33
+ min-width: 100%;
34
+ }
35
+
36
+ .sun-tb-layout-fixed {
37
+ table-layout: fixed;
38
+ }
39
+
40
+ // zebra style
41
+ .sun-tb-zebra > .sun-tb-row:nth-child(odd) > .sun-tb-cell {
42
+ background: #f8fafc;
43
+ }
44
+
45
+ // table size
46
+ .sun-tb-size {
47
+ &-default {
48
+ font-size: 28rpx;
49
+
50
+ .sun-tb-cell {
51
+ padding: 18rpx 22rpx;
52
+ }
53
+ }
54
+
55
+ &-medium {
56
+ font-size: 26rpx;
57
+
58
+ .sun-tb-cell {
59
+ padding: 16rpx 20rpx;
60
+ }
61
+ }
62
+
63
+ &-small {
64
+ font-size: 24rpx;
65
+
66
+ .sun-tb-cell {
67
+ padding: 14rpx 18rpx;
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,3 @@
1
+ @use "./table";
2
+ @use "./table-row";
3
+ @use "./table-cell";
@@ -0,0 +1,3 @@
1
+ export { default as SunTbCell } from './table-cell.vue';
2
+ export { default as SunTbRow } from './table-row.vue';
3
+ export { default as SunTb } from './table.vue';
@@ -0,0 +1,26 @@
1
+ <template>
2
+ <view v-bind="$attrs" class="sun-tb-cell" :class="cls" :style="{ width: width, 'min-width': width, 'max-width': maxWidth }">
3
+ <slot></slot>
4
+ </view>
5
+ </template>
6
+
7
+ <script lang="ts" setup>
8
+ import { computed } from 'vue';
9
+
10
+ const props = defineProps<{
11
+ sticky?: 'left' | 'right',
12
+ width?: string,
13
+ maxWidth?: string,
14
+ /** 溢出省略 */
15
+ ellipsis?: boolean,
16
+ /** 文本换行 */
17
+ breakWord?: boolean
18
+ }>();
19
+
20
+ const cls = computed(() => ({
21
+ 'sun-tb-cell-sticky-left': props.sticky === 'left',
22
+ 'sun-tb-cell-sticky-right': props.sticky === 'right',
23
+ 'sun-tb-cell-ellipsis': props.ellipsis,
24
+ 'sun-tb-cell-break-word': props.breakWord,
25
+ }));
26
+ </script>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <view v-bind="$attrs" class="sun-tb-row" :class="{ 'sun-tb-head': head, 'sun-tb-foot': foot }">
3
+ <slot></slot>
4
+ </view>
5
+ </template>
6
+
7
+ <script lang="ts" setup>
8
+ defineProps<{
9
+ head?: boolean,
10
+ foot?: boolean,
11
+ }>();
12
+ </script>
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <view v-bind="$attrs" class="sun-tb" :class="tableClass">
3
+ <view class="sun-tb-inner" :class="tableInnerClass">
4
+ <slot></slot>
5
+ </view>
6
+ </view>
7
+ </template>
8
+
9
+ <script lang="ts" setup>
10
+ import { computed } from 'vue';
11
+
12
+ const props = withDefaults(
13
+ defineProps<{
14
+ rounded?: boolean,
15
+ bordered?: boolean,
16
+ outerBordered?: boolean,
17
+ /** 斑马风格 */
18
+ zebra?: boolean
19
+ size?: 'small' | 'medium' | 'default',
20
+ layout?: 'auto' | 'fixed'
21
+ }>(),
22
+ {
23
+ rounded: true,
24
+ outerBordered: true
25
+ }
26
+ );
27
+
28
+ const tableClass = computed(() => ({
29
+ 'sun-tb-rounded': props.rounded,
30
+ 'sun-tb-bordered': props.bordered,
31
+ 'sun-tb-outer-bordered': props.outerBordered,
32
+ [`sun-tb-size-${props.size}`]: props.size,
33
+ }));
34
+
35
+ const tableInnerClass = computed(() => ({
36
+ 'sun-tb-zebra': props.zebra,
37
+ [`sun-tb-layout-${props.layout}`]: props.layout
38
+ }));
39
+ </script>
@@ -0,0 +1,17 @@
1
+ .sun-virtual-scroll {
2
+ position: relative;
3
+ transform: translateZ(0);
4
+
5
+ &-content-container {
6
+ position: absolute;
7
+ top: 0;
8
+ left: 0;
9
+ width: inherit;
10
+ height: inherit;
11
+ }
12
+
13
+ &-item {
14
+ width: 100%;
15
+ height: 100%;
16
+ }
17
+ }
@@ -0,0 +1 @@
1
+ export { default as SunVirtualScroll } from './index.vue';