fu-kit 0.7.2 → 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.
@@ -20,7 +20,8 @@
20
20
  :key="'char' + i"
21
21
  :class="{
22
22
  '_select': i - 1 >= selection.from && i - 1 < selection.to && selection.from !== selection.to,
23
- '_cursor': i - 1 === selection.to,
23
+ '_cursor': i === selection.to,
24
+ '_cursor_0': selection.from === 0 && selection.to === 0 && i === 1,
24
25
  }"
25
26
  class="code-input_char"
26
27
  >
@@ -31,37 +32,30 @@
31
32
  </template>
32
33
 
33
34
  <script>
34
- import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
35
+ import { computed, reactive, ref } from 'vue'
35
36
 
36
37
  export default {
37
38
  name: 'ui-code-input',
38
39
  props: {
39
- modelValue: {
40
- type: String,
41
- },
42
- length: {
43
- type: Number,
44
- default: 6,
45
- },
40
+ type: { type: String, default: 'text' },
41
+ modelValue: { type: String },
42
+ length: { type: Number, default: 4 },
46
43
  },
47
44
  setup (props, { emit }) {
48
45
  const selection = reactive({ from: 0, to: 0 })
49
46
  const inp = ref(null)
50
47
 
51
48
  const selectionUpdate = (e) => {
52
- selection.from = e.target.selectionStart
53
- selection.to = e.target.selectionEnd
49
+ requestAnimationFrame(() => {
50
+ selection.from = e.target.selectionStart
51
+ selection.to = e.target.selectionEnd
52
+ })
54
53
  }
55
54
 
56
- const handleInput = (e) => {
57
- emit('update:modelValue', e.target.value)
58
- }
55
+ const handleInput = (e) => emit('update:modelValue', e.target.value)
59
56
 
60
57
  const chars = computed(() => (props.modelValue).split(''))
61
58
 
62
- onMounted(() => { })
63
- onBeforeUnmount(() => { })
64
-
65
59
  return { chars, selection, selectionUpdate, inp, handleInput }
66
60
  },
67
61
  }
@@ -69,10 +63,8 @@ export default {
69
63
 
70
64
  <style lang="scss" scoped>
71
65
  .code-input {
72
- --charbox-width: 34px;
73
- --chabox-height: 48px;
74
-
75
66
  display: flex;
67
+ height: var(--ui-lt-h);
76
68
 
77
69
  &_wrapper {
78
70
  position: relative;
@@ -84,36 +76,50 @@ export default {
84
76
  }
85
77
 
86
78
  &_inp {
87
- padding: 14px;
79
+ --extra-indent: calc((var(--ui-lt-h) + #{spacing(200)}));
80
+
88
81
  position: absolute;
89
- width: 100%;
90
- border: none;
91
- background: transparent;
82
+ width: calc(100% + var(--extra-indent));
83
+ height: 100%;
84
+ border: 0 none;
92
85
  font-family: var(--typo-font-mono);
93
- font-size: var(--typo-h200);
94
- letter-spacing: 41px;
86
+ font-size: var(--typo-font-ui);
87
+ letter-spacing: calc(var(--ui-lt-h) + #{spacing(200)});
88
+ margin-left: calc(var(--extra-indent) / -2);
95
89
  outline: none;
90
+ background: transparent;
96
91
  opacity: 0;
92
+ padding: 0;
97
93
  }
98
94
 
99
95
  &_char {
100
- width: var(--charbox-width);
101
- height: var(--ui-lt-h);
102
- border: 1px solid var(--charbox-border-color, var(--pal-grey300));
96
+ width: var(--ui-lt-h);
97
+ height: 100%;
98
+ border-style: var(--ui-lt-border-style);
99
+ border-width: var(--ui-lt-border-width);
100
+ border-color: var(--ui-pal-lateral);
103
101
  border-radius: var(--ui-lt-border-radius);
104
- color: var(--charbox-text-color, var(--pal-grey900));
102
+ background: var(--ui-pal-bg);
103
+ color: var(--ui-pal-text);
105
104
  align-items: center;
106
105
  justify-content: center;
107
106
  display: flex;
107
+ gap: spacing(100);
108
108
 
109
109
  &-item {
110
- border-width: 2px 0;
110
+ font-family: var(--typo-font-mono);
111
+ font-size: var(--typo-h300);
112
+ border-width: 0 2px 0 2px;
111
113
  border-style: solid;
112
114
  border-color: transparent;
113
115
  background: transparent;
114
- min-width: 0.75em;
115
- min-height: 1.5em;
116
116
  text-align: center;
117
+ display: flex;
118
+ align-items: center;
119
+ justify-content: center;
120
+ padding: spacing(200);
121
+ min-width: calc(var(--ui-lt-h) / 2);
122
+ min-height: calc(var(--ui-lt-h) / 2);
117
123
  }
118
124
 
119
125
  &._select &-item {
@@ -121,12 +127,17 @@ export default {
121
127
  background: var(--pal-primary);
122
128
  }
123
129
 
124
- input:focus ~ &._cursor {
130
+ input:focus ~ &._cursor,
131
+ input:focus ~ &._cursor_0 {
125
132
  border-color: var(--ui-pal);
126
133
  }
127
134
 
128
- input:focus ~ &._cursor &-item {
129
- border-bottom-color: var(--pal-front);
135
+ input:focus ~ &._cursor &-item, {
136
+ border-right-color: var(--pal-front);
137
+ }
138
+
139
+ input:focus ~ &._cursor_0 &-item {
140
+ border-left-color: var(--pal-front);
130
141
  }
131
142
  }
132
143
  }
@@ -1,88 +1,88 @@
1
- <template>
2
- <ui-button
3
- :class="{'_hot': isCopied}"
4
- :hollow="!isCopied"
5
- class="ui-copy"
6
- v-bind="$attrs"
7
- @click="handleCopyToClipboard"
8
- >
9
- <slot />
10
- </ui-button>
11
- </template>
12
-
13
- <script>
14
- import { defineComponent, onBeforeUnmount, ref } from 'vue'
15
- import UiButton from './UiButton.vue'
16
-
17
- export default defineComponent({
18
- name: 'ui-copy',
19
- components: { UiButton },
20
- props: {
21
- value: { type: [ String, null ], required: true },
22
- },
23
- setup (props) {
24
- const isCopied = ref(false)
25
- let timeout
26
-
27
- onBeforeUnmount(() => {
28
- if (timeout) clearTimeout(timeout)
29
- })
30
-
31
- const handleCopyToClipboard = (event) => {
32
- if (navigator.clipboard) {
33
- navigator.clipboard.writeText(props.value)
34
- } else {
35
- execCopy()
36
- }
37
-
38
- isCopied.value = false
39
- requestAnimationFrame(() => (isCopied.value = true))
40
-
41
- if (timeout) clearTimeout(timeout)
42
- timeout = setTimeout(() => isCopied.value = false, 1000)
43
-
44
- event.target.blur()
45
- }
46
-
47
- // fallback
48
- const execCopy = () => {
49
- const textArea = document.createElement('textarea')
50
- textArea.value = props.value
51
- textArea.setAttribute('readonly', '')
52
- textArea.style.position = 'absolute'
53
- textArea.style.left = '-9999px'
54
- document.body.appendChild(textArea)
55
- textArea.select()
56
-
57
- try {
58
- document.execCommand('copy')
59
- } catch (err) {
60
- console.error(err)
61
- } finally {
62
- document.body.removeChild(textArea)
63
- }
64
- }
65
-
66
- return {
67
- handleCopyToClipboard,
68
- isCopied,
69
- }
70
- },
71
- })
72
- </script>
73
-
74
- <style lang="scss" scoped>
75
- @import "../../scss";
76
-
77
- .ui-copy {
78
- padding: spacing(0, 200);
79
- @include ellipsis();
80
-
81
- --ui-lt-h: 2em;
82
- --ui-pal: var(--pal-grey900);
83
-
84
- &._hot {
85
- color: var(--pal-positive);
86
- }
87
- }
88
- </style>
1
+ <template>
2
+ <ui-button
3
+ :class="{'_hot': isCopied}"
4
+ :hollow="!isCopied"
5
+ class="ui-copy"
6
+ v-bind="$attrs"
7
+ @click="handleCopyToClipboard"
8
+ >
9
+ <slot />
10
+ </ui-button>
11
+ </template>
12
+
13
+ <script>
14
+ import { defineComponent, onBeforeUnmount, ref } from 'vue'
15
+ import UiButton from './UiButton.vue'
16
+
17
+ export default defineComponent({
18
+ name: 'ui-copy',
19
+ components: { UiButton },
20
+ props: {
21
+ value: { type: [ String, null ], required: true },
22
+ },
23
+ setup (props) {
24
+ const isCopied = ref(false)
25
+ let timeout
26
+
27
+ onBeforeUnmount(() => {
28
+ if (timeout) clearTimeout(timeout)
29
+ })
30
+
31
+ const handleCopyToClipboard = (event) => {
32
+ if (navigator.clipboard) {
33
+ navigator.clipboard.writeText(props.value)
34
+ } else {
35
+ execCopy()
36
+ }
37
+
38
+ isCopied.value = false
39
+ requestAnimationFrame(() => (isCopied.value = true))
40
+
41
+ if (timeout) clearTimeout(timeout)
42
+ timeout = setTimeout(() => isCopied.value = false, 1000)
43
+
44
+ event.target.blur()
45
+ }
46
+
47
+ // fallback
48
+ const execCopy = () => {
49
+ const textArea = document.createElement('textarea')
50
+ textArea.value = props.value
51
+ textArea.setAttribute('readonly', '')
52
+ textArea.style.position = 'absolute'
53
+ textArea.style.left = '-9999px'
54
+ document.body.appendChild(textArea)
55
+ textArea.select()
56
+
57
+ try {
58
+ document.execCommand('copy')
59
+ } catch (err) {
60
+ console.error(err)
61
+ } finally {
62
+ document.body.removeChild(textArea)
63
+ }
64
+ }
65
+
66
+ return {
67
+ handleCopyToClipboard,
68
+ isCopied,
69
+ }
70
+ },
71
+ })
72
+ </script>
73
+
74
+ <style lang="scss" scoped>
75
+ @import "../../scss";
76
+
77
+ .ui-copy {
78
+ padding: spacing(0, 200);
79
+ @include ellipsis();
80
+
81
+ --ui-lt-h: 2em;
82
+ --ui-pal: var(--pal-grey900);
83
+
84
+ &._hot {
85
+ color: var(--pal-positive);
86
+ }
87
+ }
88
+ </style>
@@ -1,109 +1,109 @@
1
- <template>
2
- <div
3
- v-click-away="isOpen && handleClickaway"
4
- :class="{ '_is-open': !disabled && isOpen }"
5
- class="ui-dropdown"
6
- >
7
- <div class="ui-dropdown_trigger" @click="toggle">
8
- <slot :isOpen="!disabled && isOpen" />
9
- </div>
10
-
11
- <div v-if="!disabled && isOpen" ref="slotWrap" :class="{ _right: snapToRight }" class="ui-dropdown_content">
12
- <slot :dropdownClose="close" name="content" />
13
- </div>
14
- </div>
15
- </template>
16
-
17
- <script>
18
- // todo: rewrite to composition
19
-
20
- import { directive as clickAway } from 'vue3-click-away'
21
-
22
- import { defineComponent } from 'vue'
23
-
24
- export default defineComponent({
25
- name: 'ui-dropdown',
26
- directives: { clickAway },
27
- props: {
28
- clickaway: { type: Boolean, default: true },
29
- snapToRight: { type: Boolean, default: false },
30
- disabled: { type: Boolean, default: false },
31
- },
32
- emits: [ 'open', 'close' ],
33
- data () {
34
- return {
35
- isOpen: false,
36
- }
37
- },
38
-
39
- watch: {
40
- isOpen (value) {
41
- this.$emit(value ? 'open' : 'close')
42
- },
43
- },
44
-
45
- methods: {
46
- handleClickaway (e) {
47
- /* v-on-click-outside don't recognize slots */
48
- const path = e.path || (e.composedPath && e.composedPath())
49
- if (path.includes(this.$refs.slotWrap)) return
50
-
51
- if (this.clickaway && this.isOpen) {
52
- this.toggle()
53
- }
54
- },
55
- toggle () {
56
- if (this.disabled) return
57
- this.isOpen = !this.isOpen
58
- },
59
- close () {
60
- this.isOpen = false
61
- },
62
- },
63
- })
64
- </script>
65
-
66
- <style lang="scss" scoped>
67
- @import "../../scss";
68
-
69
- .ui-dropdown {
70
- @include typo(200);
71
-
72
- padding: 0;
73
- box-sizing: border-box;
74
- position: relative;
75
-
76
- &_trigger {
77
- display: flex;
78
- align-items: center;
79
- justify-content: stretch;
80
- }
81
-
82
- &_content {
83
- @include scrollbar-awesome();
84
-
85
- overflow: auto;
86
- min-width: 100%;
87
- max-width: 100vw;
88
- max-height: var(--ui-dropdown-max-height);
89
- flex-direction: column;
90
- justify-content: stretch;
91
- border-radius: var(--ui-lt-border-radius);
92
- position: absolute;
93
- top: 100%;
94
- background: var(--ui-pal-bg);
95
- margin-top: spacing(200);
96
- z-index: var(--lt-z-pop);
97
- background: var(--pal-bg);
98
- box-shadow: 0 3px 11px rgba(var(--rgb-front), 0.2);
99
-
100
- &:not(._right) {
101
- left: 0;
102
- }
103
-
104
- &._right {
105
- right: 0;
106
- }
107
- }
108
- }
109
- </style>
1
+ <template>
2
+ <div
3
+ v-click-away="isOpen && handleClickaway"
4
+ :class="{ '_is-open': !disabled && isOpen }"
5
+ class="ui-dropdown"
6
+ >
7
+ <div class="ui-dropdown_trigger" @click="toggle">
8
+ <slot :isOpen="!disabled && isOpen" />
9
+ </div>
10
+
11
+ <div v-if="!disabled && isOpen" ref="slotWrap" :class="{ _right: snapToRight }" class="ui-dropdown_content">
12
+ <slot :dropdownClose="close" name="content" />
13
+ </div>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ // todo: rewrite to composition
19
+
20
+ import { directive as clickAway } from 'vue3-click-away'
21
+
22
+ import { defineComponent } from 'vue'
23
+
24
+ export default defineComponent({
25
+ name: 'ui-dropdown',
26
+ directives: { clickAway },
27
+ props: {
28
+ clickaway: { type: Boolean, default: true },
29
+ snapToRight: { type: Boolean, default: false },
30
+ disabled: { type: Boolean, default: false },
31
+ },
32
+ emits: [ 'open', 'close' ],
33
+ data () {
34
+ return {
35
+ isOpen: false,
36
+ }
37
+ },
38
+
39
+ watch: {
40
+ isOpen (value) {
41
+ this.$emit(value ? 'open' : 'close')
42
+ },
43
+ },
44
+
45
+ methods: {
46
+ handleClickaway (e) {
47
+ /* v-on-click-outside don't recognize slots */
48
+ const path = e.path || (e.composedPath && e.composedPath())
49
+ if (path.includes(this.$refs.slotWrap)) return
50
+
51
+ if (this.clickaway && this.isOpen) {
52
+ this.toggle()
53
+ }
54
+ },
55
+ toggle () {
56
+ if (this.disabled) return
57
+ this.isOpen = !this.isOpen
58
+ },
59
+ close () {
60
+ this.isOpen = false
61
+ },
62
+ },
63
+ })
64
+ </script>
65
+
66
+ <style lang="scss" scoped>
67
+ @import "../../scss";
68
+
69
+ .ui-dropdown {
70
+ @include typo(200);
71
+
72
+ padding: 0;
73
+ box-sizing: border-box;
74
+ position: relative;
75
+
76
+ &_trigger {
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: stretch;
80
+ }
81
+
82
+ &_content {
83
+ @include scrollbar-awesome();
84
+
85
+ overflow: auto;
86
+ min-width: 100%;
87
+ max-width: 100vw;
88
+ max-height: var(--ui-dropdown-max-height);
89
+ flex-direction: column;
90
+ justify-content: stretch;
91
+ border-radius: var(--ui-lt-border-radius);
92
+ position: absolute;
93
+ top: 100%;
94
+ background: var(--ui-pal-bg);
95
+ margin-top: spacing(200);
96
+ z-index: var(--lt-z-pop);
97
+ background: var(--pal-bg);
98
+ box-shadow: 0 3px 11px rgba(var(--rgb-front), 0.2);
99
+
100
+ &:not(._right) {
101
+ left: 0;
102
+ }
103
+
104
+ &._right {
105
+ right: 0;
106
+ }
107
+ }
108
+ }
109
+ </style>
@@ -1,66 +1,66 @@
1
- <template>
2
- <div
3
- :class="{
4
- '_interactive': interactive || autoClose,
5
- '_active': active,
6
- }"
7
- class="ui-dropdown-item"
8
- @click="handleClick"
9
- >
10
- <slot />
11
- </div>
12
- </template>
13
-
14
- <script>
15
- import { defineComponent } from 'vue'
16
-
17
- export default defineComponent({
18
- name: 'ui-dropdown-item',
19
- props: {
20
- autoClose: { type: Boolean, default: false },
21
- interactive: { type: Boolean, default: false },
22
- active: { type: Boolean, default: false },
23
- look: { type: [ String ], default: 'default' },
24
- },
25
- methods: {
26
- handleClick () {
27
- if (this.autoClose) {
28
- this.$parent.close()
29
- }
30
- },
31
- },
32
- })
33
- </script>
34
-
35
- <style lang="scss" scoped>
36
- @import "../../scss";
37
-
38
- .ui-dropdown-item {
39
- padding: spacing(200) spacing(400);
40
- display: flex;
41
- align-items: center;
42
- min-height: var(--ui-lt-h);
43
-
44
- &._interactive {
45
- color: var(--ui-pal-text);
46
- cursor: pointer;
47
-
48
- &:hover {
49
- color: var(--ui-pal);
50
- }
51
-
52
- &:focus,
53
- &:active {
54
- outline: none;
55
- }
56
- }
57
-
58
- &._active {
59
- outline: none;
60
- color: var(--ui-pal);
61
-
62
- &:hover {
63
- }
64
- }
65
- }
66
- </style>
1
+ <template>
2
+ <div
3
+ :class="{
4
+ '_interactive': interactive || autoClose,
5
+ '_active': active,
6
+ }"
7
+ class="ui-dropdown-item"
8
+ @click="handleClick"
9
+ >
10
+ <slot />
11
+ </div>
12
+ </template>
13
+
14
+ <script>
15
+ import { defineComponent } from 'vue'
16
+
17
+ export default defineComponent({
18
+ name: 'ui-dropdown-item',
19
+ props: {
20
+ autoClose: { type: Boolean, default: false },
21
+ interactive: { type: Boolean, default: false },
22
+ active: { type: Boolean, default: false },
23
+ look: { type: [ String ], default: 'default' },
24
+ },
25
+ methods: {
26
+ handleClick () {
27
+ if (this.autoClose) {
28
+ this.$parent.close()
29
+ }
30
+ },
31
+ },
32
+ })
33
+ </script>
34
+
35
+ <style lang="scss" scoped>
36
+ @import "../../scss";
37
+
38
+ .ui-dropdown-item {
39
+ padding: spacing(200) spacing(400);
40
+ display: flex;
41
+ align-items: center;
42
+ min-height: var(--ui-lt-h);
43
+
44
+ &._interactive {
45
+ color: var(--ui-pal-text);
46
+ cursor: pointer;
47
+
48
+ &:hover {
49
+ color: var(--ui-pal);
50
+ }
51
+
52
+ &:focus,
53
+ &:active {
54
+ outline: none;
55
+ }
56
+ }
57
+
58
+ &._active {
59
+ outline: none;
60
+ color: var(--ui-pal);
61
+
62
+ &:hover {
63
+ }
64
+ }
65
+ }
66
+ </style>