@globalbrain/sefirot 2.0.0-draft.1 → 2.0.0-draft.5

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/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ # [2.0.0-draft.5](https://github.com/globalbrain/sefirot/compare/v2.0.0-draft.4...v2.0.0-draft.5) (2022-02-16)
2
+
3
+ ### Features
4
+
5
+ * **icon:** add a mail icon ([#115](https://github.com/globalbrain/sefirot/issues/115)) ([b3c24a7](https://github.com/globalbrain/sefirot/commit/b3c24a7602936fcba3fdc5ea51a8600adb15ec2c))
6
+
7
+ # [2.0.0-draft.4](https://github.com/globalbrain/sefirot/compare/v2.0.0-draft.3...v2.0.0-draft.4) (2021-12-22)
8
+
9
+ ### Features
10
+
11
+ * refactor modals ([36d0d1e](https://github.com/globalbrain/sefirot/commit/36d0d1e7747935aff4d909d4023751002875d6c8))
12
+
13
+ # [2.0.0-draft.3](https://github.com/globalbrain/sefirot/compare/v2.0.0-draft.2...v2.0.0-draft.3) (2021-12-17)
14
+
15
+ ### Features
16
+
17
+ * **input-text:** emit "enter" and "blur" event ([a7b2b38](https://github.com/globalbrain/sefirot/commit/a7b2b38dc5f4880e7b680601be6e607d9b180c68))
18
+
19
+ # [2.0.0-draft.2](https://github.com/globalbrain/sefirot/compare/v2.0.0-draft.1...v2.0.0-draft.2) (2021-12-14)
20
+
21
+ ### Bug Fixes
22
+
23
+ * **input-number:** emit null when empty is input ([#111](https://github.com/globalbrain/sefirot/issues/111)) ([d417960](https://github.com/globalbrain/sefirot/commit/d417960884b5c3b09c793058b80fcbc17351ecd3))
24
+
1
25
  # [2.0.0-draft.1](https://github.com/globalbrain/sefirot/compare/v0.71.0...v2.0.0-draft.1) (2021-12-13)
2
26
 
3
27
  Initial release.
@@ -59,7 +59,7 @@ interface Value {
59
59
 
60
60
  type ValueType = 'hour' | 'minute' | 'second'
61
61
 
62
- export interface Fields {
62
+ interface Fields {
63
63
  hour?: boolean
64
64
  minute?: boolean
65
65
  second?: boolean
@@ -37,7 +37,7 @@ defineProps({
37
37
 
38
38
  const emit = defineEmits(['update:modelValue'])
39
39
 
40
- function emitUpdate(value: string): void {
41
- emit('update:modelValue', value === '' ? null : Number(value))
40
+ function emitUpdate(value: string | null): void {
41
+ emit('update:modelValue', value ? Number(value): null)
42
42
  }
43
43
  </script>
@@ -16,6 +16,7 @@
16
16
  :value="modelValue"
17
17
  @input="emitInput"
18
18
  @blur="emitBlur"
19
+ @keypress.enter="emitEnter"
19
20
  >
20
21
  </SInputBase>
21
22
  </template>
@@ -40,7 +41,11 @@ const props = defineProps({
40
41
  validation: { type: Object as PropType<Validatable>, default: null }
41
42
  })
42
43
 
43
- const emit = defineEmits(['update:modelValue'])
44
+ const emit = defineEmits<{
45
+ (e: 'update:modelValue', value: string | null): void
46
+ (e: 'blur', value: string | null): void
47
+ (e: 'enter', value: string | null): void
48
+ }>()
44
49
 
45
50
  const classes = computed(() => [
46
51
  props.size,
@@ -52,11 +57,24 @@ function emitInput(e: Event): void {
52
57
  }
53
58
 
54
59
  function emitBlur(e: FocusEvent): void {
60
+ const value = getValue(e)
61
+
55
62
  props.validation?.$touch()
56
- emit('update:modelValue', getValue(e))
63
+
64
+ emit('update:modelValue', value)
65
+ emit('blur', value)
66
+ }
67
+
68
+ function emitEnter(e: KeyboardEvent): void {
69
+ const value = getValue(e)
70
+
71
+ props.validation?.$touch()
72
+
73
+ emit('update:modelValue', value)
74
+ emit('enter', value)
57
75
  }
58
76
 
59
- function getValue(e: Event | FocusEvent): string | null {
77
+ function getValue(e: Event | FocusEvent | KeyboardEvent): string | null {
60
78
  const value = (e.target as HTMLInputElement).value
61
79
 
62
80
  return value === '' ? null : value
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <div v-show="show" class="SModal" ref="el" @click="closeIfClosable">
3
- <div class="content" @click="closeIfClosable">
4
- <component :is="component" v-bind="data" @close="close" />
2
+ <div v-show="show" class="SModal" ref="el">
3
+ <div class="content">
4
+ <component :is="component" v-bind="data ?? {}" @close="close" />
5
5
  </div>
6
6
  </div>
7
7
  </template>
@@ -10,15 +10,16 @@
10
10
  import { ref, onMounted, onBeforeUnmount } from 'vue'
11
11
  import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock'
12
12
 
13
- const props = defineProps({
14
- id: { type: Number, default: null },
15
- component: { type: Object, default: () => ({}) },
16
- data: { type: Object, default: () => ({}) },
17
- show: { type: Boolean, required: true },
18
- closable: { type: Boolean, default: true }
19
- })
13
+ const props = defineProps<{
14
+ id?: number
15
+ component: any
16
+ data?: Record<string, any>
17
+ show: boolean
18
+ }>()
20
19
 
21
- const emit = defineEmits(['close'])
20
+ const emit = defineEmits<{
21
+ (e: 'close', id?: number): void
22
+ }>()
22
23
 
23
24
  const el = ref<any>(null)
24
25
 
@@ -29,34 +30,16 @@ function close() {
29
30
  emit('close', props.id)
30
31
  }
31
32
 
32
- function closeIfClosable(e: any): void {
33
- if (props.closable) {
34
- if (!isDescendant(e.target)) {
35
- close()
36
- }
37
- }
38
- }
39
-
40
- function isDescendant(el: any): boolean {
41
- if (el.classList && el.classList.contains('content')) {
42
- return false
43
- }
44
-
45
- const parent = document.getElementsByClassName('content')[0]
46
-
47
- return parent && parent.contains(el)
48
- }
49
-
50
- function lock(): void {
33
+ function lock() {
51
34
  disableBodyScroll(el.value!, { reserveScrollBarGap: true })
52
35
  }
53
36
 
54
- function release(): void {
37
+ function release() {
55
38
  enableBodyScroll(el.value!)
56
39
  }
57
40
  </script>
58
41
 
59
- <style lang="postcss" scoped>
42
+ <style scoped lang="postcss">
60
43
  .SModal {
61
44
  position: absolute;
62
45
  top: 0;
@@ -64,13 +47,8 @@ function release(): void {
64
47
  bottom: 0;
65
48
  left: 0;
66
49
  height: 100vh;
67
- padding: 32px 16px 96px;
68
50
  overflow: hidden;
69
51
  overflow-y: auto;
70
-
71
- @media (min-width: 768px) {
72
- padding: 48px 24px 96px;
73
- }
74
52
  }
75
53
 
76
54
  .SModal.fade-enter-active .content,
@@ -9,7 +9,6 @@
9
9
  :show="index === items.length - 1"
10
10
  :component="item.component"
11
11
  :data="item.data"
12
- :closable="item.options && item.options.closable"
13
12
  @close="id => close(id)"
14
13
  />
15
14
  </transition-group>
@@ -43,7 +42,7 @@ watch(hasItem, (value) => {
43
42
 
44
43
  watch(route, closeAll)
45
44
 
46
- function close(id: number) {
45
+ function close(id?: number) {
47
46
  store.dispatch('modal/close', id)
48
47
  }
49
48
 
@@ -52,7 +51,7 @@ function closeAll() {
52
51
  }
53
52
  </script>
54
53
 
55
- <style lang="postcss" scoped>
54
+ <style scoped lang="postcss">
56
55
  .SPortalModals {
57
56
  position: fixed;
58
57
  top: 0;
@@ -1,34 +1,92 @@
1
1
  <template>
2
- <article class="SSheet" :class="[size ?? 'medium']">
3
- <slot :close="close" />
4
- </article>
2
+ <div class="SSheet" :class="[size ?? 'medium']" @click="closeIfClosable">
3
+ <article class="box" @click.stop>
4
+ <div v-if="closable !== false" class="close">
5
+ <button class="close-button" @click="$emit('close')">
6
+ <SIconX class="close-icon" />
7
+ </button>
8
+ </div>
9
+
10
+ <slot :close="() => emit('close')" />
11
+ </article>
12
+ </div>
5
13
  </template>
6
14
 
7
15
  <script setup lang="ts">
8
- import { useStore } from 'vuex'
16
+ import SIconX from './icons/SIconX.vue'
9
17
 
10
- defineProps<{
18
+ const props = defineProps<{
11
19
  size?: 'small' | 'medium' | 'large'
20
+ closable?: boolean
12
21
  }>()
13
22
 
14
- const store = useStore()
23
+ const emit = defineEmits<{
24
+ (e: 'close'): void
25
+ }>()
15
26
 
16
- function close() {
17
- store.dispatch('modal/close')
27
+ function closeIfClosable() {
28
+ if (props.closable !== false) {
29
+ emit('close')
30
+ }
18
31
  }
19
32
  </script>
20
33
 
21
- <style lang="postcss" scoped>
34
+ <style scoped lang="postcss">
22
35
  .SSheet {
36
+ padding: 16px 16px 96px;
37
+ min-height: 100vh;
38
+
39
+ @media (min-width: 512px) {
40
+ padding: 32px 24px 96px;
41
+ }
42
+
43
+ @media (min-width: 768px) {
44
+ padding: 48px 32px 128px;
45
+ }
46
+ }
47
+
48
+ .SSheet.small .box { max-width: 392px; }
49
+ .SSheet.medium .box { max-width: 512px; }
50
+ .SSheet.large .box { max-width: 768px; }
51
+
52
+ .box {
53
+ position: relative;
23
54
  margin: 0 auto;
24
55
  border: 1px solid var(--c-divider-light);
25
56
  border-radius: 8px;
26
57
  background-color: var(--c-bg);
27
58
  box-shadow: var(--shadow-depth-3);
28
- overflow: hidden;
29
59
  }
30
60
 
31
- .SSheet.small { max-width: 392px; }
32
- .SSheet.medium { max-width: 512px; }
33
- .SSheet.large { max-width: 768px; }
61
+ .close {
62
+ position: absolute;
63
+ top: 10px;
64
+ right: 4px;
65
+ z-index: 10;
66
+
67
+ @media (min-width: 512px) {
68
+ top: 14px;
69
+ right: 12px;
70
+ }
71
+ }
72
+
73
+ .close-button {
74
+ display: flex;
75
+ justify-content: center;
76
+ align-items: center;
77
+ width: 48px;
78
+ height: 48px;
79
+ color: var(--c-text-3);
80
+ transition: color .25s;
81
+
82
+ &:hover {
83
+ color: var(--c-text-1);
84
+ }
85
+ }
86
+
87
+ .close-icon {
88
+ width: 20px;
89
+ height: 20px;
90
+ fill: currentColor;
91
+ }
34
92
  </style>
@@ -4,9 +4,13 @@
4
4
  </footer>
5
5
  </template>
6
6
 
7
- <style lang="postcss" scoped>
7
+ <style scoped lang="postcss">
8
8
  .SSheetFooter {
9
9
  border-top: 1px solid var(--c-divider-light);
10
10
  padding: 0 16px;
11
+
12
+ @media (min-width: 512px) {
13
+ padding: 0 24px;
14
+ }
11
15
  }
12
16
  </style>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="SSheetFooterAction">
3
3
  <SButton
4
- size="medium"
4
+ size="small"
5
5
  :type="type ?? 'primary'"
6
6
  :mode="mode ?? 'neutral'"
7
7
  :label="label"
@@ -8,7 +8,7 @@
8
8
  .SSheetFooterActions {
9
9
  display: flex;
10
10
  justify-content: flex-end;
11
- padding: 12px 0 11px;
11
+ padding: 16px 0 15px;
12
12
  }
13
13
 
14
14
  .SSheetFooterActions :deep(.SSheetFooterAction + .SSheetFooterAction) {
@@ -6,17 +6,11 @@
6
6
 
7
7
  <style lang="postcss" scoped>
8
8
  .SSheetMedium {
9
- padding: 16px;
10
- }
9
+ padding: 12px 16px 20px;
11
10
 
12
- .SSheetMedium :deep(h1) {
13
- line-height: 32px;
14
- font-size: 20px;
15
- font-weight: 500;
16
- }
17
-
18
- .SSheetMedium :deep(h1 + p) {
19
- margin-top: 8px;
11
+ @media (min-width: 512px) {
12
+ padding: 16px 24px 26px;
13
+ }
20
14
  }
21
15
 
22
16
  .SSheetMedium :deep(p) {
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <header class="SSheetTitle">
3
+ <h1 class="title">
4
+ <slot />
5
+ </h1>
6
+ </header>
7
+ </template>
8
+
9
+ <style lang="postcss" scoped>
10
+ .title {
11
+ padding: 20px 48px 0 16px;
12
+ line-height: 28px;
13
+ font-size: 20px;
14
+ font-weight: 500;
15
+
16
+ @media (min-width: 512px) {
17
+ padding: 24px 64px 0 24px;
18
+ }
19
+ }
20
+ </style>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
3
+ <path d="M20,21H4a3,3,0,0,1-3-3V6A3,3,0,0,1,4,3H20a3,3,0,0,1,3,3V18A3,3,0,0,1,20,21ZM4,5A1,1,0,0,0,3,6V18a1,1,0,0,0,1,1H20a1,1,0,0,0,1-1V6a1,1,0,0,0-1-1Z" />
4
+ <path d="M12,14a1,1,0,0,1-.57-.18l-10-7A1,1,0,1,1,2.57,5.18L12,11.78l9.43-6.6a1,1,0,1,1,1.14,1.64l-10,7A1,1,0,0,1,12,14Z" />
5
+ </svg>
6
+ </template>
@@ -14,7 +14,7 @@ export interface Search {
14
14
  placeholder: string
15
15
  missing: string
16
16
  value: Ref<string>
17
- onInput (text: string): void
17
+ onInput (text: string | null): void
18
18
  }
19
19
 
20
20
  export type Item = TextItem | UserItem
@@ -1,29 +1,21 @@
1
1
  import { useStore } from 'vuex'
2
- import { Options as ModalOptions } from '../store/modal'
3
2
 
4
3
  export interface Modal {
5
- open(item?: OpenOptions): Promise<any>
4
+ open(data?: Record<string, any>): Promise<any>
6
5
  close(): Promise<any>
7
6
  }
8
7
 
9
- export interface OpenOptions {
10
- id?: number
11
- component?: any
12
- data?: Record<string, any>
13
- options?: ModalOptions
14
- }
15
-
16
8
  let modalId = 0
17
9
 
18
10
  export function useModal(component: any): Modal {
19
11
  const store = useStore()
20
12
  const id = useModalId()
21
13
 
22
- function open(item: OpenOptions = {}) {
14
+ function open(data: Record<string, any> = {}): Promise<any> {
23
15
  return store.dispatch('modal/open', {
24
16
  id,
25
17
  component,
26
- ...item
18
+ data
27
19
  })
28
20
  }
29
21
 
@@ -1,7 +1,6 @@
1
1
  import { App } from 'vue'
2
2
  import SSheet from '../components/SSheet.vue'
3
- import SSheetHeader from '../components/SSheetHeader.vue'
4
- import SSheetHeaderTitle from '../components/SSheetHeaderTitle.vue'
3
+ import SSheetTitle from '../components/SSheetTitle.vue'
5
4
  import SSheetMedium from '../components/SSheetMedium.vue'
6
5
  import SSheetFooter from '../components/SSheetFooter.vue'
7
6
  import SSheetFooterActions from '../components/SSheetFooterActions.vue'
@@ -11,8 +10,7 @@ export function mixin(app: App): void {
11
10
  app.mixin({
12
11
  components: {
13
12
  SSheet,
14
- SSheetHeader,
15
- SSheetHeaderTitle,
13
+ SSheetTitle,
16
14
  SSheetMedium,
17
15
  SSheetFooter,
18
16
  SSheetFooterActions,
@@ -9,11 +9,6 @@ export interface Item {
9
9
  id?: number
10
10
  component: any
11
11
  data?: Record<string, any>
12
- options?: Options
13
- }
14
-
15
- export interface Options {
16
- closable?: boolean
17
12
  }
18
13
 
19
14
  function state(): State {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globalbrain/sefirot",
3
- "version": "2.0.0-draft.1",
3
+ "version": "2.0.0-draft.5",
4
4
  "description": "Vue Components for Global Brain Design System.",
5
5
  "files": [
6
6
  "lib"
@@ -9,8 +9,8 @@
9
9
  "type": "vue-tsc --noEmit",
10
10
  "lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix './{lib,tests}/**/*.{ts,vue}'",
11
11
  "lint:fail": "eslint --ext .js,.vue --ignore-path .gitignore './{lib,tests}/**/*.{ts,vue}'",
12
- "jest": "jest",
13
- "coverage": "jest --collect-coverage",
12
+ "vitest": "vitest",
13
+ "coverage": "vitest run --coverage",
14
14
  "test": "yarn type && yarn lint && yarn coverage",
15
15
  "test:fail": "yarn type && yarn lint:fail && yarn coverage",
16
16
  "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
@@ -33,50 +33,50 @@
33
33
  "peerDependencies": {
34
34
  "@types/body-scroll-lock": "^3.1.0",
35
35
  "@types/lodash-es": "^4.17.5",
36
- "@vuelidate/core": "^2.0.0-alpha.32",
37
- "@vuelidate/validators": "^2.0.0-alpha.25",
36
+ "@vuelidate/core": "^2.0.0-alpha.34",
37
+ "@vuelidate/validators": "^2.0.0-alpha.26",
38
38
  "body-scroll-lock": "^4.0.0-beta.0",
39
- "fuse.js": "^6.4.6",
39
+ "fuse.js": "^6.5.3",
40
40
  "lodash-es": "^4.17.21",
41
41
  "normalize.css": "^8.0.1",
42
- "postcss": "^8.4.4",
42
+ "postcss": "^8.4.6",
43
43
  "postcss-nested": "^5.0.6",
44
- "typescript": "^4.4.0",
45
- "vue": "^3.2.0",
44
+ "typescript": "^4.5.5",
45
+ "vue": "^3.2.31",
46
46
  "vue-router": "^4.0.12",
47
- "vue-tsc": "^0.3.0",
47
+ "vue-tsc": "^0.31.4",
48
48
  "vuex": "^4.0.2"
49
49
  },
50
50
  "devDependencies": {
51
- "@babel/core": "^7.16.0",
51
+ "@babel/core": "^7.17.4",
52
52
  "@types/body-scroll-lock": "^3.1.0",
53
- "@types/jest": "^27.0.3",
54
- "@types/lodash-es": "^4.17.5",
55
- "@typescript-eslint/parser": "^5.2.0",
53
+ "@types/lodash-es": "^4.17.6",
54
+ "@typescript-eslint/parser": "^5.12.0",
55
+ "@vitejs/plugin-vue": "^2.2.0",
56
56
  "@vue/test-utils": "^2.0.0-rc.17",
57
- "@vuelidate/core": "^2.0.0-alpha.32",
58
- "@vuelidate/validators": "^2.0.0-alpha.25",
59
- "babel-jest": "^26.0.0",
57
+ "@vuelidate/core": "^2.0.0-alpha.34",
58
+ "@vuelidate/validators": "^2.0.0-alpha.26",
60
59
  "body-scroll-lock": "^4.0.0-beta.0",
60
+ "c8": "^7.11.0",
61
61
  "codecov": "^3.8.3",
62
- "conventional-changelog-cli": "^2.1.1",
62
+ "conventional-changelog-cli": "^2.2.2",
63
63
  "dayjs": "^1.10.7",
64
- "eslint": "^8.3.0",
65
- "eslint-plugin-jest": "^25.3.0",
66
- "eslint-plugin-vue": "^8.0.1",
67
- "fuse.js": "^6.4.6",
68
- "jest": "^26.0.0",
69
- "lodash": "^4.17.21",
64
+ "enquirer": "^2.3.6",
65
+ "eslint": "^8.9.0",
66
+ "eslint-plugin-vue": "^8.4.1",
67
+ "execa": "^5.1.1",
68
+ "fuse.js": "^6.5.3",
69
+ "happy-dom": "^2.31.1",
70
70
  "lodash-es": "^4.17.21",
71
71
  "normalize.css": "^8.0.1",
72
- "postcss": "^8.4.4",
72
+ "postcss": "^8.4.6",
73
73
  "postcss-nested": "^5.0.6",
74
- "ts-jest": "^26.0.0",
75
- "typescript": "^4.4.0",
76
- "vue": "^3.2.0",
77
- "vue-jest": "^5.0.0-alpha.10",
74
+ "typescript": "^4.5.5",
75
+ "vite": "^2.8.3",
76
+ "vitest": "^0.3.5",
77
+ "vue": "^3.2.31",
78
78
  "vue-router": "^4.0.12",
79
- "vue-tsc": "^0.3.0",
79
+ "vue-tsc": "^0.31.4",
80
80
  "vuex": "^4.0.2"
81
81
  }
82
82
  }
package/lib/.DS_Store DELETED
Binary file
Binary file
@@ -1,60 +0,0 @@
1
- <template>
2
- <header class="SSheetHeader">
3
- <slot />
4
-
5
- <div v-if="closable" class="close">
6
- <button class="close-button" @click="close">
7
- <SIconX class="close-icon" />
8
- </button>
9
- </div>
10
- </header>
11
- </template>
12
-
13
- <script setup lang="ts">
14
- import { useStore } from 'vuex'
15
- import SIconX from './icons/SIconX.vue'
16
-
17
- defineProps({
18
- closable: { type: Boolean, default: true }
19
- })
20
-
21
- const store = useStore()
22
-
23
- function close() {
24
- store.dispatch('modal/close')
25
- }
26
- </script>
27
-
28
- <style lang="postcss" scoped>
29
- .SSheetHeader {
30
- display: flex;
31
- justify-content: space-between;
32
- border-bottom: 1px solid var(--c-divider-light);
33
- min-height: 48px;
34
- background-color: var(--c-bg-soft);
35
- }
36
-
37
- .close {
38
- margin: 0 0 0 auto;
39
- }
40
-
41
- .close-button {
42
- display: flex;
43
- justify-content: center;
44
- align-items: center;
45
- width: 48px;
46
- height: 47px;
47
- color: var(--c-text-3);
48
- transition: color .25s;
49
-
50
- &:hover {
51
- color: var(--c-text-1);
52
- }
53
- }
54
-
55
- .close-icon {
56
- width: 20px;
57
- height: 20px;
58
- fill: currentColor;
59
- }
60
- </style>
@@ -1,15 +0,0 @@
1
- <template>
2
- <h1 class="SSheetHeaderTitle">
3
- <slot />
4
- </h1>
5
- </template>
6
-
7
- <style lang="postcss" scoped>
8
- .SSheetHeaderTitle {
9
- margin: 0;
10
- padding: 14px 16px 10px;
11
- line-height: 20px;
12
- font-size: 14px;
13
- font-weight: 500;
14
- }
15
- </style>
Binary file