@kiva/kv-components 3.2.0 → 3.4.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,45 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [3.4.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.3.1...@kiva/kv-components@3.4.0) (2022-08-29)
7
+
8
+
9
+ ### Features
10
+
11
+ * creating a global resuable component (KvAccordionItem) ([5bf7685](https://github.com/kiva/kv-ui-elements/commit/5bf76858508870f9055e680406a1167cdd68099c))
12
+
13
+
14
+
15
+
16
+
17
+ ## [3.3.1](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.3.0...@kiva/kv-components@3.3.1) (2022-08-26)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * ensure ref is defined in exported methods ([3ab00ea](https://github.com/kiva/kv-ui-elements/commit/3ab00ea181ee2455925c2f8f01950b79c2ea7b09))
23
+
24
+
25
+
26
+
27
+
28
+ # [3.3.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.2.0...@kiva/kv-components@3.3.0) (2022-08-10)
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * added class to placeholder story to show support ([ed4e6c9](https://github.com/kiva/kv-ui-elements/commit/ed4e6c984b6a52b238862004266ada10c9cb0c95))
34
+ * added non-static class and style to placeholder as example ([4fd5e98](https://github.com/kiva/kv-ui-elements/commit/4fd5e98d41c900f69b56614980c688ebd43f6176))
35
+
36
+
37
+ ### Features
38
+
39
+ * placeholder component ([b29facc](https://github.com/kiva/kv-ui-elements/commit/b29facc8c8fcdb9761cc9e58e2530ea1e3b4a2f8))
40
+
41
+
42
+
43
+
44
+
6
45
  # [3.2.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.1.0...@kiva/kv-components@3.2.0) (2022-08-04)
7
46
 
8
47
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kiva/kv-components",
3
- "version": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -68,5 +68,5 @@
68
68
  "optional": true
69
69
  }
70
70
  },
71
- "gitHead": "d5530b779a1ae57e21fb31a23d0098deec908502"
71
+ "gitHead": "fa419acdf33c3d416a926999f23e43d3cfa882b9"
72
72
  }
@@ -0,0 +1,72 @@
1
+ /* eslint-disable no-param-reassign */
2
+
3
+ function setInitialStyle(el, { property, delay, easing }) {
4
+ el.style.overflow = 'hidden';
5
+ el.style.transition = `${property} ${delay}ms ${easing}`;
6
+ }
7
+
8
+ function unsetStyles(el, { property }) {
9
+ el.style[property] = null;
10
+ el.style.overflow = null;
11
+ el.style.transition = null;
12
+ }
13
+
14
+ export function expand(el, {
15
+ easing = 'ease',
16
+ delay = 500,
17
+ done = () => {},
18
+ from = 0,
19
+ property = 'height',
20
+ }) {
21
+ // set initial styles
22
+ setInitialStyle(el, { property, delay, easing });
23
+
24
+ // need to measure the property, so first set the value to 'auto'
25
+ // then unset display:none from v-show
26
+ el.style[property] = 'auto';
27
+ el.style.display = null;
28
+
29
+ // measure the property
30
+ const propValue = window.getComputedStyle(el).getPropertyValue(property);
31
+
32
+ // set the property to the 'from' value
33
+ el.style[property] = from;
34
+
35
+ el.addEventListener('transitionend', function listener() {
36
+ unsetStyles(el, { property });
37
+ // finally, call the done callback after the transition
38
+ done();
39
+ el.removeEventListener('transitionend', listener, true);
40
+ }, true);
41
+
42
+ // hack to cause the browser to reflow
43
+ void el.offsetWidth; // eslint-disable-line no-void
44
+ // ...and set the property to the measured value on the next tick so it animates w/ css
45
+ el.style[property] = propValue;
46
+ }
47
+
48
+ export function collapse(el, {
49
+ easing = 'ease',
50
+ delay = 500,
51
+ done = () => {},
52
+ to = 0,
53
+ property = 'height',
54
+ }) {
55
+ // set initial styles
56
+ setInitialStyle(el, { property, delay, easing });
57
+
58
+ // explicitly set the property value...
59
+ el.style[property] = window.getComputedStyle(el).getPropertyValue(property);
60
+
61
+ el.addEventListener('transitionend', function listener() {
62
+ unsetStyles(el, { property });
63
+ // finally, call the done callback after the transition
64
+ done();
65
+ el.removeEventListener('transitionend', listener, true);
66
+ }, true);
67
+
68
+ // hack to cause the browser to reflow
69
+ void el.offsetWidth; // eslint-disable-line no-void
70
+ // ...and set the property to the 'to' value on the next tick so it animates w/ css
71
+ el.style[property] = to;
72
+ }
@@ -0,0 +1,130 @@
1
+ <template>
2
+ <div
3
+ class="tw-border-b tw-border-tertiary tw-relative last:tw-border-b-0"
4
+ >
5
+ <button
6
+ class="tw-w-full tw-flex tw-justify-between tw-items-center tw-py-1.5 tw-px-0
7
+ tw-text-left disabled:tw-cursor-not-allowed disabled:tw-opacity-low
8
+ hover:tw-text-action-highlight focus:tw-text-action-highlight"
9
+ :disabled="disabled"
10
+ :aria-controls="`kv-accordion-${id}`"
11
+ :aria-expanded="isOpen ? 'true' : 'false'"
12
+ @click.prevent="toggle"
13
+ >
14
+ <span class="tw-flex-1">
15
+ <slot name="header"></slot>
16
+ </span>
17
+ <kv-material-icon
18
+ class="tw-h-3 tw-w-3 tw-transition tw-transform tw-duration-500 tw-ease"
19
+ :class="{ 'tw-rotate-180' : isOpen }"
20
+ :icon="mdiChevronDown"
21
+ />
22
+ </button>
23
+ <kv-expandable>
24
+ <div
25
+ v-show="isOpen"
26
+ :id="`kv-accordion-${id}`"
27
+ :aria-hidden="isOpen ? 'false' : 'true'"
28
+ >
29
+ <slot></slot>
30
+ </div>
31
+ </kv-expandable>
32
+ </div>
33
+ </template>
34
+
35
+ <script>
36
+ // Accordion a11y resources
37
+ // https://www.w3.org/TR/wai-aria-practices-1.1/examples/accordion/accordion.html
38
+ // https://www.aditus.io/patterns/accordion/
39
+ // Future improvement
40
+ // Currently the slot content is inside the button, which means h2, h3 etc. won't be
41
+ // navigatable via headings. See https://daverupert.com/2019/12/why-details-is-not-an-accordion/
42
+ // h2 + button // ✅ H1 will show up when navigating by headings
43
+ // button + h2 // ❌ H1 will not show up when navigating by headings
44
+ // Perhaps we could do some magic DOM reordering via this.$slots.header or
45
+ // pass a prop like 'tag' that sets the parent node of the button. <accordion tag="h3">...
46
+
47
+ import {
48
+ ref,
49
+ toRefs,
50
+ } from 'vue-demi';
51
+ import { mdiChevronDown } from '@mdi/js';
52
+ import KvExpandable from './KvExpandable.vue';
53
+ import KvMaterialIcon from './KvMaterialIcon.vue';
54
+
55
+ export default {
56
+ components: {
57
+ KvMaterialIcon,
58
+ KvExpandable,
59
+ },
60
+ props: {
61
+ /**
62
+ * Unique id. used for a11y
63
+ * */
64
+ id: {
65
+ type: String,
66
+ required: true,
67
+ validator: (v) => v.length > 0 && !/\s/g.test(v), // must be a valid html5 id
68
+ },
69
+ /**
70
+ * Whether the body is shown initially
71
+ * */
72
+ open: {
73
+ type: Boolean,
74
+ default: false,
75
+ },
76
+ /**
77
+ * Whether the accordion can be toggled
78
+ * */
79
+ disabled: {
80
+ type: Boolean,
81
+ default: false,
82
+ },
83
+ },
84
+ emits: [
85
+ 'toggle',
86
+ ],
87
+ setup(props, { emit }) {
88
+ const {
89
+ open,
90
+ disabled,
91
+ } = toRefs(props);
92
+
93
+ const isOpen = ref(open.value);
94
+
95
+ const toggle = () => {
96
+ if (!disabled.value) {
97
+ isOpen.value = !isOpen.value;
98
+ /**
99
+ * Fires when the accordion has been toggled.
100
+ * Contains an object with a boolean 'open' property of the current open
101
+ * state of the accordion
102
+ * @event toggle
103
+ * @type {Event}
104
+ */
105
+ emit('toggle', { open: isOpen.value });
106
+ }
107
+ };
108
+
109
+ const expand = () => {
110
+ if (!disabled.value) {
111
+ isOpen.value = true;
112
+ }
113
+ };
114
+
115
+ const collapse = () => {
116
+ if (!disabled.value) {
117
+ isOpen.value = false;
118
+ }
119
+ };
120
+
121
+ return {
122
+ collapse,
123
+ expand,
124
+ isOpen,
125
+ mdiChevronDown,
126
+ toggle,
127
+ };
128
+ },
129
+ };
130
+ </script>
@@ -0,0 +1,84 @@
1
+ <template>
2
+ <transition
3
+ @enter="enter"
4
+ @leave="leave"
5
+ >
6
+ <slot></slot>
7
+ </transition>
8
+ </template>
9
+
10
+ <script>
11
+ import {
12
+ toRefs,
13
+ } from 'vue-demi';
14
+ import { expand, collapse } from '../utils/expander';
15
+
16
+ export default {
17
+ props: {
18
+ property: {
19
+ type: String,
20
+ default: 'height',
21
+ },
22
+ delay: {
23
+ type: Number,
24
+ default: 500,
25
+ },
26
+ easing: {
27
+ type: String,
28
+ default: 'ease',
29
+ },
30
+ skipEnter: {
31
+ type: Boolean,
32
+ default: false,
33
+ },
34
+ skipLeave: {
35
+ type: Boolean,
36
+ default: false,
37
+ },
38
+ },
39
+ setup(props) {
40
+ const {
41
+ property,
42
+ delay,
43
+ easing,
44
+ skipEnter,
45
+ skipLeave,
46
+ } = toRefs(props);
47
+
48
+ const enter = (el, done) => {
49
+ if (skipEnter.value) {
50
+ return done();
51
+ }
52
+
53
+ expand(el, {
54
+ property: property.value,
55
+ delay: delay.value,
56
+ easing: easing.value,
57
+ done,
58
+ });
59
+
60
+ return true;
61
+ };
62
+
63
+ const leave = (el, done) => {
64
+ if (skipLeave.value) {
65
+ return done();
66
+ }
67
+
68
+ collapse(el, {
69
+ property: property.value,
70
+ delay: delay.value,
71
+ easing: easing.value,
72
+ done,
73
+ });
74
+
75
+ return true;
76
+ };
77
+
78
+ return {
79
+ enter,
80
+ leave,
81
+ };
82
+ },
83
+ };
84
+ </script>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <div
3
+ class="
4
+ loading-placeholder
5
+ tw-w-full tw-h-full
6
+ tw-relative
7
+ tw-overflow-hidden
8
+ tw-bg-tertiary
9
+ tw-rounded-sm
10
+ "
11
+ >
12
+ </div>
13
+ </template>
14
+
15
+ <style scoped>
16
+ .loading-placeholder::before {
17
+ content: '';
18
+ display: block;
19
+ position: absolute;
20
+ height: 100%;
21
+ width: 100%;
22
+ top: 0;
23
+ transform: translateX(100%);
24
+ background:
25
+ linear-gradient(to right, transparent 0%, rgb(var(--bg-secondary)) 50%, transparent 100%);
26
+ animation: loading-placeholder 1.5s infinite cubic-bezier(0.4, 0, 0.2, 1);
27
+ }
28
+
29
+ @keyframes loading-placeholder {
30
+ from {
31
+ transform: translateX(-100%);
32
+ }
33
+
34
+ to {
35
+ transform: translateX(100%);
36
+ }
37
+ }
38
+ </style>
@@ -240,6 +240,7 @@ export default {
240
240
  styles,
241
241
  inputAttrs,
242
242
  inputListeners,
243
+ textInputRef,
243
244
  };
244
245
  },
245
246
  };
@@ -0,0 +1,24 @@
1
+ import KvAccordionItem from '../KvAccordionItem.vue';
2
+
3
+ export default {
4
+ title: 'KvAccordionItem',
5
+ component: KvAccordionItem,
6
+ };
7
+
8
+ const DefaultTemplate = () => ({
9
+ components: { KvAccordionItem },
10
+ template: `
11
+ <div style="padding: 20px;">
12
+ <kv-accordion-item id="accordian-test">
13
+ <template #header>
14
+ <h2>Accordion</h2>
15
+ </template>
16
+ <p>
17
+ "Hello, KvAccordion Contents!"
18
+ </p>
19
+ </kv-accordion-item>
20
+ </div>
21
+ `,
22
+ });
23
+
24
+ export const Default = DefaultTemplate.bind({});
@@ -0,0 +1,17 @@
1
+ import KvLoadingPlaceholder from '../KvLoadingPlaceholder.vue';
2
+
3
+ export default {
4
+ title: 'KvLoadingPlaceholder',
5
+ component: KvLoadingPlaceholder,
6
+ };
7
+
8
+ const DefaultTemplate = () => ({
9
+ components: { KvLoadingPlaceholder },
10
+ template: `
11
+ <div style="padding: 20px;">
12
+ <kv-loading-placeholder class="tw-py-1" :class="{ 'tw-px-1': true }" style="height: 50px;" :style="{ width: '400px' }" />
13
+ </div>
14
+ `,
15
+ });
16
+
17
+ export const Default = DefaultTemplate.bind({});