@teammodlr/ui-kit 2.0.2 → 2.0.4

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 (32) hide show
  1. package/lib/components/colorpicker/ColorPicker.vue.d.ts +2 -0
  2. package/lib/components/colorpicker/style/ColorPicker.css.d.ts +1 -0
  3. package/lib/components/form/Form.vue.d.ts +0 -3
  4. package/lib/components/form/symbol.d.ts +9 -0
  5. package/lib/components/select/Select.vue.d.ts +4 -0
  6. package/lib/components/select/style/Select.css.d.ts +1 -0
  7. package/lib/components/table/Table.vue.d.ts +1 -3
  8. package/lib/components/table/style/Table.css.d.ts +4 -0
  9. package/lib/components/table/style/index.d.ts +1 -0
  10. package/lib/components/table/types/index.d.ts +1 -0
  11. package/lib/index.cjs.js +4 -4
  12. package/lib/index.es.js +2262 -2205
  13. package/lib/style.css +1 -1
  14. package/package.json +1 -1
  15. package/src/components/button/Button.vue +4 -1
  16. package/src/components/button/style/Button.css.ts +1 -0
  17. package/src/components/checkbox/style/Checkbox.css.ts +4 -1
  18. package/src/components/colorpicker/ColorPicker.vue +46 -6
  19. package/src/components/colorpicker/style/ColorPicker.css.ts +26 -6
  20. package/src/components/form/Form.vue +14 -12
  21. package/src/components/form/examples/basic.vue +1 -1
  22. package/src/components/form/style/Form.css.ts +1 -1
  23. package/src/components/form/symbol.ts +11 -0
  24. package/src/components/select/Select.vue +68 -52
  25. package/src/components/select/style/Select.css.ts +10 -2
  26. package/src/components/table/Table.vue +7 -4
  27. package/src/components/table/TableCell.vue +1 -1
  28. package/src/components/table/examples/basic.vue +2 -2
  29. package/src/components/table/style/Table.css.ts +81 -0
  30. package/src/components/table/style/index.ts +1 -0
  31. package/src/components/table/types/index.ts +1 -0
  32. package/src/composables/useInput.ts +5 -10
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div ref="selectRef" tabindex="0" @focus="focusSelect" @blur="open = false" style="outline: none">
2
+ <div ref="selectRef" tabindex="-1">
3
3
  <label v-if="label" :for="id" :class="style.label" :id="`${id}-label`">
4
4
  {{ label }}
5
5
  </label>
@@ -7,51 +7,52 @@
7
7
  {{ description }}
8
8
  </div>
9
9
 
10
- <div :class="style.wrapper" v-on="inputListeners" :id="id" ref="container" @click="openSelect" :aria-disabled="disabled ? 'true' : 'false'" :aria-labelledby="`${id}-label`" tabindex="0">
11
- <div class="m-select__wrapper">
12
-
13
- <div :class="selectComputedClasses">
14
- <template v-if="multiple && Array.isArray(selected) && selected.length > 0">
15
- <MTag
10
+ <div :class="computedWrapperClasses" v-on="inputListeners" :id="id" ref="container"
11
+ :aria-disabled="disabled ? 'true' : 'false'" :aria-labelledby="`${id}-label`" tabindex="0"
12
+ @focusin="focusSelect" @focusout="open = false">
13
+
14
+ <div :class="selectComputedClasses">
15
+ <template v-if="multiple && Array.isArray(selected) && selected.length > 0">
16
+ <MTag
16
17
  v-for="value in selected"
17
18
  :key="value"
18
19
  :closeable="true"
19
20
  @close="removeSelected(value)"
20
21
  :size="size"
21
- >
22
- {{ getSelectedLabel(value) }}
23
- </MTag>
24
- </template>
25
- <template v-else-if="!multiple && selected">
26
- {{ getSelectedLabel(selected) }}
27
- </template>
28
- <template v-else>
29
- <div :class="style.placeholder">{{ placeholder }}</div>
30
- </template>
31
- </div>
32
-
33
- <Teleport :to="'body'">
34
- <Transition :name="transitionName">
35
- <div :class="style.menu" v-if="isOpen" ref="popper" :style="computedConsistentWidth" :aria-hidden="isOpen ? 'false' : 'true'">
36
- <div v-if="searchable" :class="style.search">
37
- <MInput v-model="search" placeholder="Search" size="sm" ref="searchRef" />
38
- </div>
39
- <div :class="style.options">
40
- <div v-for="(option, index) in computedOptions" :key="index" ref="optionsRef"
41
- :class="{
22
+ >
23
+ {{ getSelectedLabel(value) }}
24
+ </MTag>
25
+ </template>
26
+ <template v-else-if="!multiple && selected">
27
+ {{ getSelectedLabel(selected) }}
28
+ </template>
29
+ <template v-else>
30
+ <div :class="style.placeholder">{{ placeholder }}</div>
31
+ </template>
32
+ </div>
33
+
34
+ <Teleport :to="'body'">
35
+ <Transition :name="transitionName">
36
+ <div :class="style.menu" v-if="isOpen" ref="popper" :style="computedConsistentWidth"
37
+ :aria-hidden="isOpen ? 'false' : 'true'">
38
+ <div v-if="searchable" :class="style.search">
39
+ <MInput v-model="search" placeholder="Search" size="sm" ref="searchRef"/>
40
+ </div>
41
+ <div :class="style.options">
42
+ <div v-for="(option, index) in computedOptions" :key="index" ref="optionsRef"
43
+ :class="{
42
44
  [style.option]: true,
43
45
  [style.optionSelected]: option.active,
44
46
  [style.optionFocused]: selectedIndex === index
45
- }"
46
- @click="option.onClick"
47
- @hover="selectedIndex = index">
48
- {{ option.label }}
49
- </div>
47
+ }"
48
+ @click="option.onClick"
49
+ @hover="selectedIndex = index">
50
+ {{ option.label }}
50
51
  </div>
51
52
  </div>
52
- </Transition>
53
- </Teleport>
54
- </div>
53
+ </div>
54
+ </Transition>
55
+ </Teleport>
55
56
  </div>
56
57
  <div v-if="inputError" :class="style.errorMessage">
57
58
  {{ inputError }}
@@ -60,10 +61,10 @@
60
61
  </template>
61
62
 
62
63
  <script lang="ts">
63
- import { useInput } from "../../composables/useInput";
64
- import { usePopper, type Placement } from "../../composables/usePopper";
65
- import type { Size } from "../../types/props";
66
- import { onClickOutside, useEventListener } from '@vueuse/core';
64
+ import {useInput} from "../../composables/useInput";
65
+ import {usePopper, type Placement} from "../../composables/usePopper";
66
+ import type {Size} from "../../types/props";
67
+ import {onClickOutside, useEventListener} from '@vueuse/core';
67
68
  import {
68
69
  computed,
69
70
  defineComponent,
@@ -71,9 +72,10 @@ import {
71
72
  ref,
72
73
  watch,
73
74
  watchEffect,
75
+ defineExpose,
74
76
  type PropType
75
77
  } from "vue";
76
- import { MInput, MTag } from "..";
78
+ import {MInput, MTag} from "..";
77
79
  import * as style from "./style";
78
80
  import {useInteractive} from "../../composables/useInteractive";
79
81
 
@@ -142,21 +144,23 @@ export default defineComponent({
142
144
  MInput,
143
145
  MTag
144
146
  },
145
- setup(props, { emit }) {
146
- const container = ref<HTMLElement|null>(null);
147
+ setup(props, {emit}) {
148
+ const container = ref<HTMLElement | null>(null);
147
149
  const wrapper = ref<HTMLElement>();
148
150
  const optionsRef = ref<HTMLElement[]>();
149
151
  const searchRef = ref<HTMLElement>();
150
152
  const selectRef = ref<HTMLElement>();
151
153
  const selectedIndex = ref<number | undefined>(0);
152
154
  const open = ref<boolean>(false);
155
+ const focused = ref<boolean>(false);
153
156
  const search = ref<string>('');
154
157
  const placement = ref<Placement>("bottom-start");
155
158
  const transfer = ref(false);
156
159
  const width = ref<number>(0);
157
160
  const keyboardNavigation = ref<boolean>(false);
158
161
 
159
- const { focus, blur } = useInteractive(container);
162
+
163
+ const {focus, blur} = useInteractive(container);
160
164
  // TODO: Add debounce on keyboard movement (hover flicks it back up)
161
165
  const {
162
166
  id,
@@ -165,9 +169,9 @@ export default defineComponent({
165
169
  formError,
166
170
  formDisabled,
167
171
  formLoading
168
- } = useInput(props, { focus, emit, withListeners: false });
172
+ } = useInput(props, {focus, emit, withListeners: false});
169
173
 
170
- const { popper } = usePopper({
174
+ const {popper} = usePopper({
171
175
  placement,
172
176
  transfer,
173
177
  reference: container,
@@ -234,7 +238,7 @@ export default defineComponent({
234
238
  } else {
235
239
  active = selected.value === value;
236
240
  }
237
-
241
+
238
242
  return {
239
243
  value: value,
240
244
  label: option[props.optionLabel],
@@ -428,11 +432,21 @@ export default defineComponent({
428
432
  ]
429
433
  });
430
434
 
435
+ const computedWrapperClasses = computed(() => {
436
+ return [
437
+ style.wrapper,
438
+ {
439
+ [style.focused]: focused.value,
440
+ }
441
+ ]
442
+ });
443
+
431
444
  const selectComputedClasses = computed(() => {
432
445
  return [
433
446
  style.base,
434
447
  {
435
448
  [style.selectedTags]: props.multiple,
449
+ [style.focused]: open.value,
436
450
  // [`m-select--${props.size}`]: props.size,
437
451
  'm-select--disabled': disabled.value || loading.value,
438
452
  'm-select--focused': open.value,
@@ -455,8 +469,8 @@ export default defineComponent({
455
469
  useEventListener(searchRef, 'keydown', handleKeyDown)
456
470
 
457
471
  onClickOutside(container, () => {
458
- open.value = false;
459
- }, { ignore: [searchRef, popper] });
472
+ open.value = false;
473
+ }, {ignore: [searchRef, popper]});
460
474
 
461
475
  watchEffect(() => {
462
476
  if (container.value && open.value) {
@@ -469,7 +483,7 @@ export default defineComponent({
469
483
  return;
470
484
  }
471
485
  if (typeof index !== 'undefined' && optionsRef.value) {
472
- optionsRef.value[index].scrollIntoView({ block: 'nearest', inline: 'nearest' });
486
+ optionsRef.value[index].scrollIntoView({block: 'nearest', inline: 'nearest'});
473
487
  }
474
488
  })
475
489
 
@@ -478,7 +492,7 @@ export default defineComponent({
478
492
  if (value && optionsRef.value) {
479
493
  const index = computedOptions.value.findIndex((i) => i.value === selected.value);
480
494
  if (index !== -1) {
481
- optionsRef.value[index].scrollIntoView({ block: 'center', inline: 'nearest' });
495
+ optionsRef.value[index].scrollIntoView({block: 'center', inline: 'nearest'});
482
496
  selectedIndex.value = index;
483
497
  }
484
498
  }
@@ -527,6 +541,7 @@ export default defineComponent({
527
541
 
528
542
  containerComputedClasses,
529
543
  selectComputedClasses,
544
+ computedWrapperClasses,
530
545
  computedConsistentWidth,
531
546
 
532
547
  getSelectedLabel,
@@ -535,7 +550,8 @@ export default defineComponent({
535
550
  inputError,
536
551
  transitionName,
537
552
  inputListeners,
538
- style
553
+ style,
554
+ focused
539
555
  }
540
556
  }
541
557
  });
@@ -1,5 +1,6 @@
1
- import {createVar, style} from "@vanilla-extract/css";
2
- import {themeVars} from "../../../styles/theme.css";
1
+ import { createVar, globalStyle, style, styleVariants } from "@vanilla-extract/css";
2
+ import { themeVars } from "../../../styles/theme.css";
3
+ import { fonts } from "../../../styles/typography.css";
3
4
 
4
5
  const sizes = {
5
6
  xs: '26px',
@@ -152,6 +153,13 @@ export const error = style({
152
153
  },
153
154
  });
154
155
 
156
+ export const focused = style({
157
+ vars: {
158
+ [vars.borderColor]: themeVars.color.blue[500],
159
+ },
160
+ boxShadow: `0 0 0 2px ${themeVars.color.blue[200]}`
161
+ });
162
+
155
163
  export const rightIcon = style({
156
164
  pointerEvents: 'none',
157
165
  position: 'absolute',
@@ -10,6 +10,7 @@
10
10
  v-for="(header, index) in headers"
11
11
  :key="index"
12
12
  :width="header.width"
13
+ :style="{ textAlign: header.align} "
13
14
  >
14
15
  {{ header.name }}
15
16
  </TableHead>
@@ -22,6 +23,7 @@
22
23
  <TableCell
23
24
  v-for="(header, index) in headers"
24
25
  :key="index"
26
+ :style="{ textAlign: header.align} "
25
27
  >
26
28
  <slot :name="header.key" :item="item">
27
29
  {{//@ts-ignore
@@ -42,6 +44,7 @@ import TableHead from './TableHead.vue';
42
44
  import TableBody from './TableBody.vue';
43
45
  import TableRow from './TableRow.vue';
44
46
  import TableCell from './TableCell.vue';
47
+ import * as style from "./style";
45
48
 
46
49
  export default defineComponent({
47
50
  name: "Table",
@@ -81,6 +84,7 @@ export default defineComponent({
81
84
 
82
85
  const wrapperComputedClasses = computed(() => {
83
86
  return [
87
+ style.wrapper,
84
88
  'm-table__wrapper',
85
89
  {
86
90
  'm-table__wrapper--loading': props.loading
@@ -90,11 +94,10 @@ export default defineComponent({
90
94
 
91
95
  const tableComputedClasses = computed(() => {
92
96
  return [
93
- 'm-table',
97
+ style.table,
94
98
  {
95
- 'm-table--loading': props.loading,
96
- 'm-table--striped': props.striped,
97
- 'm-table--hover': props.hover
99
+ [style.hoverable]: props.hover,
100
+ [style.striped]: props.striped,
98
101
  }
99
102
  ]
100
103
  });
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <td>
2
+ <td >
3
3
  <slot />
4
4
  </td>
5
5
  </template>
@@ -2,7 +2,6 @@
2
2
  <MTable
3
3
  :headers="headers"
4
4
  :items="items"
5
- striped
6
5
  >
7
6
  <template #actions="{ item }">
8
7
  <MButton
@@ -32,7 +31,8 @@ let headers = ref<TableHeadItem[]>([
32
31
  },
33
32
  {
34
33
  name: "Actions",
35
- key: "actions"
34
+ key: "actions",
35
+ align: "right"
36
36
  }
37
37
  ]);
38
38
 
@@ -0,0 +1,81 @@
1
+ import { createVar, globalKeyframes, globalStyle, style, styleVariants } from "@vanilla-extract/css";
2
+ import { themeVars } from "../../../styles/theme.css";
3
+
4
+ export const wrapper = style({
5
+ width: "100%",
6
+ overflow: "auto",
7
+ });
8
+
9
+ const vars = {
10
+ headerHeight: createVar(),
11
+ cellPadding: createVar(),
12
+ fontSize: createVar()
13
+ }
14
+
15
+ export const table = style({
16
+ vars: {
17
+ [vars.headerHeight]: "44px",
18
+ [vars.cellPadding]: "8px 14px",
19
+ [vars.fontSize]: themeVars.fontSize.base,
20
+ },
21
+ width: "100%",
22
+ borderCollapse: "collapse",
23
+ fontSize: vars.fontSize
24
+ });
25
+
26
+ export const hoverable = style({});
27
+ export const striped = style({});
28
+
29
+ globalStyle(`${striped} tbody tr:nth-child(even)`, {
30
+ backgroundColor: themeVars.color.gray[50],
31
+ });
32
+
33
+ globalStyle(`${table} tbody:before`, {
34
+ content:"@",
35
+ display:"block",
36
+ lineHeight:"5px",
37
+ textIndent:"-99999px"
38
+ });
39
+
40
+ globalStyle(`${table} th`, {
41
+ height: vars.headerHeight,
42
+ padding: vars.cellPadding,
43
+ textAlign: "left",
44
+ backgroundColor: themeVars.color.gray[100],
45
+ color: themeVars.color.gray[600],
46
+ fontWeight: 500,
47
+ fontSize: themeVars.fontSize.base,
48
+ marginBottom: "5px"
49
+ });
50
+
51
+ // round first and last cells
52
+ globalStyle(`${table} th:first-child`, {
53
+ borderTopLeftRadius: themeVars.rounded.medium,
54
+ borderBottomLeftRadius: themeVars.rounded.medium,
55
+ });
56
+
57
+ globalStyle(`${table} th:last-child`, {
58
+ borderTopRightRadius: themeVars.rounded.medium,
59
+ borderBottomRightRadius: themeVars.rounded.medium,
60
+ });
61
+
62
+ globalStyle(`${table} td:first-child`, {
63
+ borderTopLeftRadius: themeVars.rounded.medium,
64
+ borderBottomLeftRadius: themeVars.rounded.medium,
65
+ });
66
+
67
+ globalStyle(`${table} td:last-child`, {
68
+ borderTopRightRadius: themeVars.rounded.medium,
69
+ borderBottomRightRadius: themeVars.rounded.medium,
70
+ });
71
+
72
+ globalStyle(`${table} td`, {
73
+ padding: vars.cellPadding,
74
+ textAlign: "left",
75
+ color: themeVars.color.gray[900],
76
+ fontWeight: 400,
77
+ });
78
+
79
+ globalStyle(`${hoverable} tr:hover td`, {
80
+ backgroundColor: themeVars.color.gray[50],
81
+ });
@@ -0,0 +1 @@
1
+ export * from './Table.css';
@@ -2,4 +2,5 @@ export type TableHeadItem = {
2
2
  key: string;
3
3
  name?: string;
4
4
  width?: string | number;
5
+ align?: 'left' | 'center' | 'right';
5
6
  }
@@ -2,6 +2,7 @@
2
2
  import type { PropType } from 'vue';
3
3
  import { ref, watch, inject, computed, onMounted, onUnmounted } from 'vue';
4
4
  import { useCachedUid } from './useCachedUid';
5
+ import {FORM_STATE} from "../components/form/symbol";
5
6
 
6
7
  export interface FormInput {
7
8
  focus: () => void;
@@ -24,13 +25,7 @@ export const useInput = (props: any, { focus, emit, withListeners = true }: {
24
25
  watch(() => props.error, (value) => formError.value = value);
25
26
  watch(() => props.name, (value) => name.value = value);
26
27
 
27
- const form = inject('m-form', {
28
- add: (inputName: string, methods: FormInput) => {},
29
- remove: (inputName: string) => {},
30
- insideForm: false,
31
- disabled: false,
32
- loading: false
33
- });
28
+ const form = inject(FORM_STATE, null);
34
29
 
35
30
  const reset = () => {
36
31
  formError.value = '';
@@ -86,7 +81,7 @@ export const useInput = (props: any, { focus, emit, withListeners = true }: {
86
81
  }) : {};
87
82
 
88
83
  onMounted(() => {
89
- form.add(_name.value,
84
+ form?.add(_name.value,
90
85
  focus,
91
86
  // @ts-ignore
92
87
  validate,
@@ -96,14 +91,14 @@ export const useInput = (props: any, { focus, emit, withListeners = true }: {
96
91
  })
97
92
 
98
93
  onUnmounted(() => {
99
- form.remove(_name.value);
94
+ form?.remove(_name.value);
100
95
  });
101
96
 
102
97
  return {
103
98
  id,
104
99
  isFirstValidation,
105
100
  formError,
106
- insideForm: form.insideForm,
101
+ insideForm: form?.insideForm ?? false,
107
102
  inputListeners,
108
103
  reset,
109
104
  validate,