@studiometa/ui 0.1.1 → 0.2.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 (54) hide show
  1. package/README.md +37 -1
  2. package/atoms/Cursor/Cursor.cjs +129 -0
  3. package/{Cursor.d.ts → atoms/Cursor/Cursor.d.ts} +0 -0
  4. package/atoms/Cursor/Cursor.js +103 -0
  5. package/atoms/Figure/Figure.cjs +53 -0
  6. package/atoms/Figure/Figure.d.ts +31 -0
  7. package/atoms/Figure/Figure.js +27 -0
  8. package/atoms/index.cjs +38 -0
  9. package/atoms/index.d.ts +2 -0
  10. package/atoms/index.js +6 -0
  11. package/index.cjs +26 -0
  12. package/index.d.ts +3 -6
  13. package/index.js +3 -6
  14. package/molecules/Accordion/Accordion.cjs +65 -0
  15. package/{Accordion/index.d.ts → molecules/Accordion/Accordion.d.ts} +5 -6
  16. package/molecules/Accordion/Accordion.js +35 -0
  17. package/molecules/Accordion/AccordionCore.cjs +60 -0
  18. package/{Accordion/Accordion.d.ts → molecules/Accordion/AccordionCore.d.ts} +0 -0
  19. package/molecules/Accordion/AccordionCore.js +34 -0
  20. package/molecules/Accordion/AccordionItem.cjs +208 -0
  21. package/{Accordion → molecules/Accordion}/AccordionItem.d.ts +3 -3
  22. package/molecules/Accordion/AccordionItem.js +178 -0
  23. package/molecules/Modal/Modal.cjs +177 -0
  24. package/{Modal.d.ts → molecules/Modal/Modal.d.ts} +0 -0
  25. package/molecules/Modal/Modal.js +151 -0
  26. package/molecules/Sticky/Sticky.cjs +133 -0
  27. package/molecules/Sticky/Sticky.d.ts +141 -0
  28. package/molecules/Sticky/Sticky.js +107 -0
  29. package/molecules/Tabs/Tabs.cjs +152 -0
  30. package/{Tabs.d.ts → molecules/Tabs/Tabs.d.ts} +0 -0
  31. package/molecules/Tabs/Tabs.js +126 -0
  32. package/molecules/index.cjs +44 -0
  33. package/molecules/index.d.ts +5 -0
  34. package/molecules/index.js +12 -0
  35. package/organisms/index.cjs +23 -0
  36. package/organisms/index.d.ts +1 -0
  37. package/organisms/index.js +0 -0
  38. package/package.json +2 -2
  39. package/primitives/Draggable/Draggable.cjs +64 -0
  40. package/{Draggable.d.ts → primitives/Draggable/Draggable.d.ts} +0 -0
  41. package/primitives/Draggable/Draggable.js +38 -0
  42. package/primitives/Sentinel/Sentinel.cjs +41 -0
  43. package/primitives/Sentinel/Sentinel.d.ts +12 -0
  44. package/primitives/Sentinel/Sentinel.js +15 -0
  45. package/primitives/index.cjs +38 -0
  46. package/primitives/index.d.ts +2 -0
  47. package/primitives/index.js +6 -0
  48. package/Accordion/Accordion.js +0 -29
  49. package/Accordion/AccordionItem.js +0 -197
  50. package/Accordion/index.js +0 -12
  51. package/Cursor.js +0 -121
  52. package/Draggable.js +0 -31
  53. package/Modal.js +0 -167
  54. package/Tabs.js +0 -106
@@ -1,197 +0,0 @@
1
- import deepmerge from 'deepmerge';
2
- import { Base } from '@studiometa/js-toolkit';
3
- import * as styles from '@studiometa/js-toolkit/utils/css/styles.js';
4
- import transition from '@studiometa/js-toolkit/utils/css/transition.js';
5
- import Accordion from './Accordion.js';
6
- export default class AccordionItem extends Base {
7
- static config = {
8
- name: 'AccordionItem',
9
- refs: ['btn', 'content', 'container'],
10
- emits: ['open', 'close'],
11
- options: {
12
- isOpen: Boolean,
13
- styles: {
14
- type: Object,
15
- default: () => ({
16
- container: {
17
- open: '',
18
- active: '',
19
- closed: ''
20
- }
21
- })
22
- }
23
- }
24
- };
25
-
26
- mounted() {
27
- if (this.$parent && this.$parent instanceof Accordion && this.$parent.$options.item) {
28
- Object.entries(this.$parent.$options.item).forEach(([key, value]) => {
29
- if (key in this.$options) {
30
- const type = AccordionItem.config.options[key].type || AccordionItem.config.options[key];
31
-
32
- if (type === Array || type === Object) {
33
- this.$options[key] = deepmerge(this.$options[key], value);
34
- } else {
35
- this.$options[key] = value;
36
- }
37
- }
38
- });
39
- }
40
-
41
- this.$refs.btn.setAttribute('id', this.$id);
42
- this.$refs.btn.setAttribute('aria-controls', this.contentId);
43
- this.$refs.content.setAttribute('aria-labelledby', this.$id);
44
- this.$refs.content.setAttribute('id', this.contentId);
45
- const {
46
- isOpen
47
- } = this.$options;
48
- this.updateAttributes(isOpen);
49
-
50
- if (!isOpen) {
51
- styles.add(this.$refs.container, {
52
- visibility: 'invisible',
53
- height: '0'
54
- });
55
- }
56
-
57
- const {
58
- container,
59
- ...otherStyles
60
- } = this.$options.styles;
61
- const refs = this.$refs;
62
- Object.entries(otherStyles).filter(([refName]) => refs[refName]).forEach(([refName, {
63
- open,
64
- closed
65
- } = {
66
- open: '',
67
- closed: ''
68
- }]) => {
69
- transition(refs[refName], {
70
- to: isOpen ? open : closed
71
- }, 'keep');
72
- });
73
- }
74
-
75
- destroyed() {
76
- styles.remove(this.$refs.container, {
77
- visibility: '',
78
- height: ''
79
- });
80
- }
81
-
82
- onBtnClick() {
83
- if (this.$options.isOpen) {
84
- this.close();
85
- } else {
86
- this.open();
87
- }
88
- }
89
-
90
- get contentId() {
91
- return `content-${this.$id}`;
92
- }
93
-
94
- updateAttributes(isOpen) {
95
- this.$refs.content.setAttribute('aria-hidden', isOpen ? 'false' : 'true');
96
- this.$refs.btn.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
97
- }
98
-
99
- async open() {
100
- if (this.$options.isOpen) {
101
- return;
102
- }
103
-
104
- this.$log('open');
105
- this.$emit('open');
106
- this.$options.isOpen = true;
107
- this.updateAttributes(this.$options.isOpen);
108
- styles.remove(this.$refs.container, {
109
- visibility: 'invisible'
110
- });
111
- const {
112
- container,
113
- ...otherStyles
114
- } = this.$options.styles;
115
- const refs = this.$refs;
116
- await Promise.all([transition(refs.container, {
117
- from: {
118
- height: 0
119
- },
120
- active: container.active,
121
- to: {
122
- height: `${refs.content.offsetHeight}px`
123
- }
124
- }).then(() => {
125
- if (this.$options.isOpen) {
126
- styles.remove(refs.content, {
127
- position: 'absolute'
128
- });
129
- }
130
-
131
- return Promise.resolve();
132
- }), ...Object.entries(otherStyles).filter(([refName]) => refs[refName]).map(([refName, {
133
- open,
134
- active,
135
- closed
136
- } = {
137
- open: '',
138
- active: '',
139
- closed: ''
140
- }]) => transition(refs[refName], {
141
- from: closed,
142
- active,
143
- to: open
144
- }, 'keep'))]);
145
- }
146
-
147
- async close() {
148
- if (!this.$options.isOpen) {
149
- return;
150
- }
151
-
152
- this.$log('close');
153
- this.$emit('close');
154
- this.$options.isOpen = false;
155
- const height = this.$refs.container.offsetHeight;
156
- styles.add(this.$refs.content, {
157
- position: 'absolute'
158
- });
159
- const {
160
- container,
161
- ...otherStyles
162
- } = this.$options.styles;
163
- const refs = this.$refs;
164
- await Promise.all([transition(refs.container, {
165
- from: {
166
- height: `${height}px`
167
- },
168
- active: container.active,
169
- to: {
170
- height: '0'
171
- }
172
- }).then(() => {
173
- if (!this.$options.isOpen) {
174
- styles.add(refs.container, {
175
- height: '0',
176
- visibility: 'invisible'
177
- });
178
- this.updateAttributes(this.$options.isOpen);
179
- }
180
-
181
- return Promise.resolve();
182
- }), ...Object.entries(otherStyles).filter(([refName]) => refs[refName]).map(([refName, {
183
- open,
184
- active,
185
- closed
186
- } = {
187
- open: '',
188
- active: '',
189
- closed: ''
190
- }]) => transition(refs[refName], {
191
- from: open,
192
- active,
193
- to: closed
194
- }, 'keep'))]);
195
- }
196
-
197
- }
@@ -1,12 +0,0 @@
1
- import AccordionCore from './Accordion.js';
2
- import AccordionItem from './AccordionItem.js';
3
-
4
- class Accordion extends AccordionCore {
5
- static config = { ...AccordionCore.config,
6
- components: {
7
- AccordionItem
8
- }
9
- };
10
- }
11
-
12
- export default Accordion;
package/Cursor.js DELETED
@@ -1,121 +0,0 @@
1
- import { Base } from '@studiometa/js-toolkit';
2
- import damp from '@studiometa/js-toolkit/utils/math/damp.js';
3
- import matrix from '@studiometa/js-toolkit/utils/css/matrix.js';
4
- export default class Cursor extends Base {
5
- static config = {
6
- name: 'Cursor',
7
- options: {
8
- growSelectors: {
9
- type: String,
10
- default: 'a, a *, button, button *, [data-cursor-grow], [data-cursor-grow] *'
11
- },
12
- shrinkSelectors: {
13
- type: String,
14
- default: '[data-cursor-shrink], [data-cursor-shrink] *'
15
- },
16
- growTo: {
17
- type: Number,
18
- default: 2
19
- },
20
- shrinkTo: {
21
- type: Number,
22
- default: 0.5
23
- },
24
- translateDampFactor: {
25
- type: Number,
26
- default: 0.25
27
- },
28
- growDampFactor: {
29
- type: Number,
30
- default: 0.25
31
- },
32
- shrinkDampFactor: {
33
- type: Number,
34
- default: 0.25
35
- }
36
- }
37
- };
38
- x = 0;
39
- y = 0;
40
- scale = 0;
41
- pointerX = 0;
42
- pointerY = 0;
43
- pointerScale = 0;
44
-
45
- mounted() {
46
- this.x = 0;
47
- this.y = 0;
48
- this.scale = 0;
49
- this.pointerX = 0;
50
- this.pointerY = 0;
51
- this.pointerScale = 0;
52
- this.render({
53
- x: this.x,
54
- y: this.y,
55
- scale: this.scale
56
- });
57
- }
58
-
59
- moved({
60
- event,
61
- x,
62
- y,
63
- isDown
64
- }) {
65
- if (!this.$services.has('ticked')) {
66
- this.$services.enable('ticked');
67
- }
68
-
69
- this.pointerX = x;
70
- this.pointerY = y;
71
- let scale = 1;
72
-
73
- if (!event) {
74
- this.pointerScale = scale;
75
- return;
76
- }
77
-
78
- const shouldGrow = event.target instanceof Element && event.target.matches(this.$options.growSelectors) || false;
79
- const shouldReduce = isDown || event.target instanceof Element && event.target.matches(this.$options.shrinkSelectors) || false;
80
-
81
- if (shouldGrow) {
82
- scale = this.$options.growTo;
83
- }
84
-
85
- if (shouldReduce) {
86
- scale = this.$options.shrinkTo;
87
- }
88
-
89
- this.pointerScale = scale;
90
- }
91
-
92
- ticked() {
93
- this.x = damp(this.pointerX, this.x, this.$options.translateDampFactor);
94
- this.y = damp(this.pointerY, this.y, this.$options.translateDampFactor);
95
- this.scale = damp(this.pointerScale, this.scale, this.pointerScale < this.scale ? this.$options.shrinkDampFactor : this.$options.growDampFactor);
96
- this.render({
97
- x: this.x,
98
- y: this.y,
99
- scale: this.scale
100
- });
101
-
102
- if (this.x === this.pointerX && this.y === this.pointerY && this.scale === this.pointerScale) {
103
- this.$services.disable('ticked');
104
- }
105
- }
106
-
107
- render({
108
- x,
109
- y,
110
- scale
111
- }) {
112
- const transform = matrix({
113
- translateX: x,
114
- translateY: y,
115
- scaleX: scale,
116
- scaleY: scale
117
- });
118
- this.$el.style.transform = `translateZ(0) ${transform}`;
119
- }
120
-
121
- }
package/Draggable.js DELETED
@@ -1,31 +0,0 @@
1
- import { animate } from 'motion';
2
- import { Base, withDrag } from '@studiometa/js-toolkit';
3
- export default class Draggable extends withDrag(Base) {
4
- static config = {
5
- name: 'DraggableElement'
6
- };
7
- static animateOptions = {
8
- easing: 'linear',
9
- duration: 0
10
- };
11
- x = 0;
12
- y = 0;
13
- originX = 0;
14
- originY = 0;
15
-
16
- dragged(props) {
17
- if (props.mode === 'start') {
18
- this.originX = this.x;
19
- this.originY = this.y;
20
- return;
21
- }
22
-
23
- this.x = this.originX + props.x - props.origin.x;
24
- this.y = this.originY + props.y - props.origin.y;
25
- animate(this.$el, {
26
- x: this.x,
27
- y: this.y
28
- }, Draggable.animateOptions);
29
- }
30
-
31
- }
package/Modal.js DELETED
@@ -1,167 +0,0 @@
1
- import { Base } from '@studiometa/js-toolkit';
2
- import transition from '@studiometa/js-toolkit/utils/css/transition.js';
3
- import { trap, untrap, saveActiveElement } from '@studiometa/js-toolkit/utils/focusTrap.js';
4
- export default class Modal extends Base {
5
- static config = {
6
- name: 'Modal',
7
- refs: ['close', 'container', 'content', 'modal', 'open', 'overlay'],
8
- emits: ['open', 'close'],
9
- options: {
10
- move: String,
11
- autofocus: {
12
- type: String,
13
- default: '[autofocus]'
14
- },
15
- styles: {
16
- type: Object,
17
- default: () => ({
18
- modal: {
19
- closed: {
20
- opacity: '0',
21
- pointerEvents: 'none',
22
- visibility: 'hidden'
23
- }
24
- }
25
- })
26
- }
27
- }
28
- };
29
-
30
- get onOpenClick() {
31
- return this.open;
32
- }
33
-
34
- get onCloseClick() {
35
- return this.close;
36
- }
37
-
38
- get onOverlayClick() {
39
- return this.close;
40
- }
41
-
42
- mounted() {
43
- this.isOpen = false;
44
- this.close();
45
-
46
- if (this.$options.move) {
47
- const target = document.querySelector(this.$options.move) || document.body;
48
- this.__refsBackup = this.$refs;
49
- this.__refModalPlaceholder = document.createComment('');
50
- this.__refModalParentBackup = this.$refs.modal.parentElement || this.$el;
51
-
52
- this.__refModalParentBackup.insertBefore(this.__refModalPlaceholder, this.$refs.modal);
53
-
54
- target.appendChild(this.$refs.modal);
55
- }
56
-
57
- return this;
58
- }
59
-
60
- get $refs() {
61
- const $refs = super.$refs;
62
-
63
- if (this.$options.move && this.__refsBackup) {
64
- Object.entries(this.__refsBackup).forEach(([key, ref]) => {
65
- if (!$refs[key]) {
66
- $refs[key] = ref;
67
- }
68
- });
69
- }
70
-
71
- return $refs;
72
- }
73
-
74
- destroyed() {
75
- this.close();
76
-
77
- if (this.$options.move && this.__refModalParentBackup) {
78
- this.__refModalParentBackup.insertBefore(this.$refs.modal, this.__refModalPlaceholder);
79
-
80
- this.__refModalPlaceholder.remove();
81
-
82
- delete this.__refModalPlaceholder;
83
- delete this.__refModalParentBackup;
84
- }
85
-
86
- return this;
87
- }
88
-
89
- keyed({
90
- event,
91
- isUp,
92
- isDown,
93
- ESC
94
- }) {
95
- if (!this.isOpen) {
96
- return;
97
- }
98
-
99
- if (isDown) {
100
- trap(this.$refs.modal, event);
101
- }
102
-
103
- if (ESC && isUp) {
104
- this.close();
105
- }
106
- }
107
-
108
- async open() {
109
- if (this.isOpen) {
110
- return Promise.resolve(this);
111
- }
112
-
113
- this.$refs.modal.setAttribute('aria-hidden', 'false');
114
- document.documentElement.style.overflow = 'hidden';
115
- this.isOpen = true;
116
- this.$emit('open');
117
- const refs = this.$refs;
118
- return Promise.all(Object.entries(this.$options.styles).map(([refName, {
119
- open,
120
- active,
121
- closed
122
- } = {
123
- open: '',
124
- active: '',
125
- closed: ''
126
- }]) => transition(refs[refName], {
127
- from: closed,
128
- active,
129
- to: open
130
- }, 'keep'))).then(() => {
131
- if (this.$options.autofocus && this.$refs.modal.querySelector(this.$options.autofocus)) {
132
- saveActiveElement();
133
- const autofocusElement = this.$refs.modal.querySelector(this.$options.autofocus);
134
- autofocusElement.focus();
135
- }
136
-
137
- return Promise.resolve(this);
138
- });
139
- }
140
-
141
- async close() {
142
- if (!this.isOpen) {
143
- return Promise.resolve(this);
144
- }
145
-
146
- this.$refs.modal.setAttribute('aria-hidden', 'true');
147
- document.documentElement.style.overflow = '';
148
- this.isOpen = false;
149
- untrap();
150
- this.$emit('close');
151
- const refs = this.$refs;
152
- return Promise.all(Object.entries(this.$options.styles).map(([refName, {
153
- open,
154
- active,
155
- closed
156
- } = {
157
- open: '',
158
- active: '',
159
- closed: ''
160
- }]) => transition(refs[refName], {
161
- from: open,
162
- active,
163
- to: closed
164
- }, 'keep'))).then(() => Promise.resolve(this));
165
- }
166
-
167
- }
package/Tabs.js DELETED
@@ -1,106 +0,0 @@
1
- import { Base } from '@studiometa/js-toolkit';
2
- import transition from '@studiometa/js-toolkit/utils/css/transition.js';
3
- export default class Tabs extends Base {
4
- static config = {
5
- name: 'Tabs',
6
- refs: ['btn[]', 'content[]'],
7
- emits: ['enable', 'disable'],
8
- options: {
9
- styles: {
10
- type: Object,
11
- default: () => ({
12
- content: {
13
- closed: {
14
- position: 'absolute',
15
- opacity: '0',
16
- pointerEvents: 'none',
17
- visibility: 'hidden'
18
- }
19
- }
20
- })
21
- }
22
- }
23
- };
24
-
25
- mounted() {
26
- this.items = this.$refs.btn.map((btn, index) => {
27
- const id = `${this.$id}-${index}`;
28
- const content = this.$refs.content[index];
29
- btn.setAttribute('id', id);
30
- content.setAttribute('aria-labelledby', id);
31
- const item = {
32
- btn,
33
- content,
34
- isEnabled: index > 0
35
- };
36
-
37
- if (index > 0) {
38
- this.disableItem(item);
39
- } else {
40
- this.enableItem(item);
41
- }
42
-
43
- return item;
44
- });
45
- }
46
-
47
- onBtnClick(event, index) {
48
- this.items.forEach((item, i) => {
49
- if (i !== index) {
50
- this.disableItem(item);
51
- }
52
- });
53
- this.enableItem(this.items[index]);
54
- }
55
-
56
- async enableItem(item) {
57
- if (!item || item.isEnabled) {
58
- return Promise.resolve(this);
59
- }
60
-
61
- item.isEnabled = true;
62
- const {
63
- btn,
64
- content
65
- } = item;
66
- const btnStyles = this.$options.styles.btn || {};
67
- const contentStyles = this.$options.styles.content || {};
68
- content.setAttribute('aria-hidden', 'false');
69
- this.$emit('enable', item);
70
- return Promise.all([transition(btn, {
71
- from: btnStyles.closed,
72
- active: btnStyles.active,
73
- to: btnStyles.open
74
- }, 'keep'), transition(content, {
75
- from: contentStyles.closed,
76
- active: contentStyles.active,
77
- to: contentStyles.open
78
- }, 'keep')]).then(() => Promise.resolve(this));
79
- }
80
-
81
- async disableItem(item) {
82
- if (!item || !item.isEnabled) {
83
- return Promise.resolve(this);
84
- }
85
-
86
- item.isEnabled = false;
87
- const {
88
- btn,
89
- content
90
- } = item;
91
- const btnStyles = this.$options.styles.btn || {};
92
- const contentStyles = this.$options.styles.content || {};
93
- content.setAttribute('aria-hidden', 'true');
94
- this.$emit('disable', item);
95
- return Promise.all([transition(btn, {
96
- from: btnStyles.open,
97
- active: btnStyles.active,
98
- to: btnStyles.closed
99
- }, 'keep'), transition(content, {
100
- from: contentStyles.open,
101
- active: contentStyles.active,
102
- to: contentStyles.closed
103
- }, 'keep')]).then(() => Promise.resolve(this));
104
- }
105
-
106
- }