@studiometa/ui 0.2.5 → 0.2.8

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 (50) hide show
  1. package/atoms/Button/Button.twig +68 -0
  2. package/atoms/Button/StyledButton.twig +47 -0
  3. package/atoms/Cursor/Cursor.twig +28 -0
  4. package/atoms/Figure/Figure.twig +120 -0
  5. package/atoms/Icon/Icon.twig +13 -0
  6. package/atoms/LargeText/LargeText.cjs +3 -3
  7. package/atoms/LargeText/LargeText.d.ts +1 -2
  8. package/atoms/LargeText/LargeText.js +1 -1
  9. package/atoms/LargeText/LargeText.twig +49 -0
  10. package/atoms/ScrollAnimation/AbstractScrollAnimation.cjs +18 -59
  11. package/atoms/ScrollAnimation/AbstractScrollAnimation.d.ts +28 -55
  12. package/atoms/ScrollAnimation/AbstractScrollAnimation.js +1 -1
  13. package/atoms/ScrollAnimation/ScrollAnimation.d.ts +9 -4
  14. package/atoms/ScrollAnimation/animationScrollWithEase.cjs +3 -24
  15. package/atoms/ScrollAnimation/animationScrollWithEase.js +1 -1
  16. package/index.cjs +1 -0
  17. package/index.d.ts +1 -0
  18. package/index.js +1 -1
  19. package/molecules/Accordion/Accordion.twig +54 -0
  20. package/molecules/Modal/Modal.twig +108 -0
  21. package/molecules/Modal/StyledModal.twig +39 -0
  22. package/molecules/Panel/Panel.twig +73 -0
  23. package/molecules/Panel/StyledPanel.twig +28 -0
  24. package/molecules/Slider/AbstractSliderChild.cjs +8 -1
  25. package/molecules/Slider/AbstractSliderChild.d.ts +2 -2
  26. package/molecules/Slider/AbstractSliderChild.js +1 -1
  27. package/molecules/Slider/Slider.cjs +12 -4
  28. package/molecules/Slider/Slider.d.ts +11 -0
  29. package/molecules/Slider/Slider.js +1 -1
  30. package/molecules/Slider/SliderBtn.d.ts +8 -0
  31. package/molecules/Slider/SliderCount.d.ts +8 -0
  32. package/molecules/Slider/SliderDots.d.ts +8 -0
  33. package/molecules/Slider/SliderDrag.cjs +5 -1
  34. package/molecules/Slider/SliderDrag.d.ts +7 -0
  35. package/molecules/Slider/SliderDrag.js +1 -1
  36. package/molecules/Slider/SliderItem.cjs +7 -6
  37. package/molecules/Slider/SliderItem.d.ts +9 -0
  38. package/molecules/Slider/SliderItem.js +1 -1
  39. package/molecules/Slider/SliderProgress.cjs +7 -3
  40. package/molecules/Slider/SliderProgress.d.ts +8 -0
  41. package/molecules/Slider/SliderProgress.js +1 -1
  42. package/molecules/Sticky/Sticky.twig +31 -0
  43. package/molecules/Tabs/Tabs.twig +20 -0
  44. package/organisms/Frame/Frame.cjs +44 -3
  45. package/organisms/Frame/Frame.d.ts +34 -1
  46. package/organisms/Frame/Frame.js +1 -1
  47. package/organisms/Frame/FrameTarget.cjs +3 -3
  48. package/organisms/Frame/FrameTarget.js +1 -1
  49. package/organisms/ImageGrid/ImageGrid.twig +42 -0
  50. package/package.json +2 -2
@@ -0,0 +1,20 @@
1
+ <div data-component="Tabs" data-option-styles='{ "btn": { "open": { "borderBottomColor": "#fff" } } }'>
2
+ {% block title_wrapper %}
3
+ {% for item in items %}
4
+ <button data-ref="btn[]" style="border-bottom: 1px solid transparent;">
5
+ {% block title %}
6
+ {{ item.title }}
7
+ {% endblock %}
8
+ </button>
9
+ {% endfor %}
10
+ {% endblock %}
11
+ {% block content_wrapper %}
12
+ {% for item in items %}
13
+ <div data-ref="content[]" aria-hidden="false">
14
+ {% block content %}
15
+ {{ item.content }}
16
+ {% endblock %}
17
+ </div>
18
+ {% endfor %}
19
+ {% endblock %}
20
+ </div>
@@ -35,6 +35,12 @@ var import_utils = require("@studiometa/js-toolkit/utils");
35
35
  var import_FrameAnchor = __toESM(require("./FrameAnchor.cjs"), 1);
36
36
  var import_FrameForm = __toESM(require("./FrameForm.cjs"), 1);
37
37
  var import_FrameTarget = __toESM(require("./FrameTarget.cjs"), 1);
38
+ function getScrollPosition() {
39
+ return {
40
+ left: window.pageXOffset,
41
+ top: window.pageYOffset
42
+ };
43
+ }
38
44
  var cache = /* @__PURE__ */ new Map();
39
45
  var _Frame = class extends import_js_toolkit.Base {
40
46
  get id() {
@@ -53,11 +59,40 @@ var _Frame = class extends import_js_toolkit.Base {
53
59
  return this.getDirectChild("FrameAnchor");
54
60
  }
55
61
  get directChildFrameForm() {
56
- return this.getDirectChild("form");
62
+ return this.getDirectChild("FrameForm");
57
63
  }
58
64
  get directChildFrameTarget() {
59
65
  return this.getDirectChild("FrameTarget");
60
66
  }
67
+ mounted() {
68
+ if (this.$options.history) {
69
+ window.addEventListener("popstate", this);
70
+ }
71
+ }
72
+ destroyed() {
73
+ window.removeEventListener("popstate", this);
74
+ }
75
+ handleEvent(event) {
76
+ if (event.type === "popstate") {
77
+ this.onWindowPopstate(event);
78
+ }
79
+ if (event.type === "beforeunload") {
80
+ this.onWindowUnload();
81
+ }
82
+ }
83
+ onWindowUnload() {
84
+ const { history } = window;
85
+ if (!history.state) {
86
+ return;
87
+ }
88
+ history.replaceState({
89
+ ...history.state,
90
+ scroll: getScrollPosition()
91
+ }, "");
92
+ }
93
+ onWindowPopstate(event) {
94
+ this.goTo(window.location.href, event.state);
95
+ }
61
96
  onFrameAnchorFrameClick(event, index) {
62
97
  if (!this.directChildFrameAnchor.includes(this.$children.FrameAnchor[index])) {
63
98
  return;
@@ -77,12 +112,14 @@ var _Frame = class extends import_js_toolkit.Base {
77
112
  this.$log("onFrameFormFrameSubmit", event);
78
113
  event.preventDefault();
79
114
  const form = this.$children.FrameForm[index];
80
- this.goTo(form.action);
115
+ const url = new URL(form.action);
116
+ url.search = new URLSearchParams(new FormData(form.$el)).toString();
117
+ this.goTo(url.toString());
81
118
  }
82
119
  parseHTML(string = "") {
83
120
  return new DOMParser().parseFromString(string, "text/html");
84
121
  }
85
- async goTo(url) {
122
+ async goTo(url, scroll = null) {
86
123
  this.$log("goTo", url);
87
124
  const parsedUrl = new URL(url);
88
125
  if (parsedUrl.origin !== window.location.origin) {
@@ -104,6 +141,10 @@ var _Frame = class extends import_js_toolkit.Base {
104
141
  document.title = doc.title;
105
142
  (0, import_utils.historyPush)({ path: parsedUrl.pathname, search: parsedUrl.searchParams });
106
143
  }
144
+ if (scroll) {
145
+ document.scrollingElement.scrollTop = scroll.top;
146
+ document.scrollingElement.scrollLeft = scroll.left;
147
+ }
107
148
  await (0, import_utils.nextFrame)();
108
149
  this.$root.$update();
109
150
  await (0, import_utils.nextFrame)();
@@ -63,6 +63,35 @@ export default class Frame extends Base {
63
63
  * @returns {FrameTarget[]}
64
64
  */
65
65
  get directChildFrameTarget(): FrameTarget[];
66
+ /**
67
+ * Mounted hook.
68
+ * @returns {void}
69
+ */
70
+ mounted(): void;
71
+ /**
72
+ * Destroyed hook.
73
+ * @returns {void}
74
+ */
75
+ destroyed(): void;
76
+ /**
77
+ * Dispatch events.
78
+ * @param {PopStateEvent} event
79
+ * @returns {void}
80
+ */
81
+ handleEvent(event: PopStateEvent): void;
82
+ /**
83
+ * Prevent scroll top on unload.
84
+ *
85
+ * @returns {void}
86
+ */
87
+ onWindowUnload(): void;
88
+ /**
89
+ * Go to the previous URL on `popstate` event.
90
+ *
91
+ * @param {PopStateEvent} event
92
+ * @returns {void}
93
+ */
94
+ onWindowPopstate(event: PopStateEvent): void;
66
95
  /**
67
96
  * Prevent click on `FrameAnchor`.
68
97
  *
@@ -90,9 +119,13 @@ export default class Frame extends Base {
90
119
  /**
91
120
  * Go to the given url.
92
121
  * @param {string} url
122
+ * @param {null|{ top: number, left: number }} [scroll]
93
123
  * @returns {Promise<void>}
94
124
  */
95
- goTo(url: string): Promise<void>;
125
+ goTo(url: string, scroll?: null | {
126
+ top: number;
127
+ left: number;
128
+ }): Promise<void>;
96
129
  /**
97
130
  * Fetch the given url.
98
131
  * @param {string} url
@@ -1 +1 @@
1
- import{Base as l}from"@studiometa/js-toolkit";import{nextFrame as c,historyPush as d}from"@studiometa/js-toolkit/utils";import f from"./FrameAnchor.js";import F from"./FrameForm.js";import g from"./FrameTarget.js";const n=new Map;class a extends l{static config={name:"Frame",emits:["before-fetch","after-fetch","before-leave","after-leave","before-content","after-content","before-enter","after-enter"],log:!0,components:{FrameAnchor:f,FrameForm:F,FrameTarget:g,Frame:a},options:{history:Boolean}};get id(){return this.$el.id}getDirectChild(e){return this.$children[e]?this.$children.Frame?this.$children[e].filter(t=>this.$children.Frame.every(r=>r.$children[e]?!r.$children[e].includes(t):!0)):this.$children[e]:[]}get directChildFrameAnchor(){return this.getDirectChild("FrameAnchor")}get directChildFrameForm(){return this.getDirectChild("form")}get directChildFrameTarget(){return this.getDirectChild("FrameTarget")}onFrameAnchorFrameClick(e,t){if(!this.directChildFrameAnchor.includes(this.$children.FrameAnchor[t]))return;this.$log("onAFrameClick",e,t),e.preventDefault();const r=this.$children.FrameAnchor[t];r.href!==window.location.href&&this.goTo(r.href)}onFrameFormFrameSubmit(e,t){if(!this.directChildFrameForm.includes(this.$children.FrameForm[t]))return;this.$log("onFrameFormFrameSubmit",e),e.preventDefault();const r=this.$children.FrameForm[t];this.goTo(r.action)}parseHTML(e=""){return new DOMParser().parseFromString(e,"text/html")}async goTo(e){this.$log("goTo",e);const t=new URL(e);if(t.origin!==window.location.origin)throw new Error("Cross origin request are not allowed.");this.$emit("before-fetch",e);const r=await this.fetch(e),i=this.parseHTML(r),h=i.querySelector(`#${this.id}`),s=new a(h);s.$children.registerAll(),this.$emit("after-fetch",e,r),this.$emit("before-leave"),await Promise.all(this.directChildFrameTarget.map(o=>o.leave())),this.$emit("after-leave"),this.$emit("before-content"),this.directChildFrameTarget.map((o,m)=>o.updateContent(s.directChildFrameTarget[m])),this.$options.history&&(document.title=i.title,d({path:t.pathname,search:t.searchParams})),await c(),this.$root.$update(),await c(),this.$emit("after-content"),this.$emit("before-enter"),await Promise.all(this.directChildFrameTarget.map(o=>o.enter())),this.$emit("after-enter")}async fetch(e){const t=n.get(e);if(t)return t.status==="pending"?t.promise:t.content;const r=fetch(e);try{n.set(e,{promise:r,status:"pending",content:void 0});const i=await r.then(h=>h.text());return n.set(e,{promise:r,status:"resolved",content:i}),i}catch(i){return n.set(e,{promise:r,status:"error",content:i}),i}}}export{a as default};
1
+ import{Base as d}from"@studiometa/js-toolkit";import{nextFrame as c,historyPush as f}from"@studiometa/js-toolkit/utils";import p from"./FrameAnchor.js";import g from"./FrameForm.js";import F from"./FrameTarget.js";function u(){return{left:window.pageXOffset,top:window.pageYOffset}}const a=new Map;class s extends d{static config={name:"Frame",emits:["before-fetch","after-fetch","before-leave","after-leave","before-content","after-content","before-enter","after-enter"],log:!0,components:{FrameAnchor:p,FrameForm:g,FrameTarget:F,Frame:s},options:{history:Boolean}};get id(){return this.$el.id}getDirectChild(e){return this.$children[e]?this.$children.Frame?this.$children[e].filter(t=>this.$children.Frame.every(r=>r.$children[e]?!r.$children[e].includes(t):!0)):this.$children[e]:[]}get directChildFrameAnchor(){return this.getDirectChild("FrameAnchor")}get directChildFrameForm(){return this.getDirectChild("FrameForm")}get directChildFrameTarget(){return this.getDirectChild("FrameTarget")}mounted(){this.$options.history&&window.addEventListener("popstate",this)}destroyed(){window.removeEventListener("popstate",this)}handleEvent(e){e.type==="popstate"&&this.onWindowPopstate(e),e.type==="beforeunload"&&this.onWindowUnload()}onWindowUnload(){const{history:e}=window;!e.state||e.replaceState({...e.state,scroll:u()},"")}onWindowPopstate(e){this.goTo(window.location.href,e.state)}onFrameAnchorFrameClick(e,t){if(!this.directChildFrameAnchor.includes(this.$children.FrameAnchor[t]))return;this.$log("onAFrameClick",e,t),e.preventDefault();const r=this.$children.FrameAnchor[t];r.href!==window.location.href&&this.goTo(r.href)}onFrameFormFrameSubmit(e,t){if(!this.directChildFrameForm.includes(this.$children.FrameForm[t]))return;this.$log("onFrameFormFrameSubmit",e),e.preventDefault();const r=this.$children.FrameForm[t],i=new URL(r.action);i.search=new URLSearchParams(new FormData(r.$el)).toString(),this.goTo(i.toString())}parseHTML(e=""){return new DOMParser().parseFromString(e,"text/html")}async goTo(e,t=null){this.$log("goTo",e);const r=new URL(e);if(r.origin!==window.location.origin)throw new Error("Cross origin request are not allowed.");this.$emit("before-fetch",e);const i=await this.fetch(e),n=this.parseHTML(i),l=n.querySelector(`#${this.id}`),h=new s(l);h.$children.registerAll(),this.$emit("after-fetch",e,i),this.$emit("before-leave"),await Promise.all(this.directChildFrameTarget.map(o=>o.leave())),this.$emit("after-leave"),this.$emit("before-content"),this.directChildFrameTarget.map((o,m)=>o.updateContent(h.directChildFrameTarget[m])),this.$options.history&&(document.title=n.title,f({path:r.pathname,search:r.searchParams})),t&&(document.scrollingElement.scrollTop=t.top,document.scrollingElement.scrollLeft=t.left),await c(),this.$root.$update(),await c(),this.$emit("after-content"),this.$emit("before-enter"),await Promise.all(this.directChildFrameTarget.map(o=>o.enter())),this.$emit("after-enter")}async fetch(e){const t=a.get(e);if(t)return t.status==="pending"?t.promise:t.content;const r=fetch(e);try{a.set(e,{promise:r,status:"pending",content:void 0});const i=await r.then(n=>n.text());return a.set(e,{promise:r,status:"resolved",content:i}),i}catch(i){return a.set(e,{promise:r,status:"error",content:i}),i}}}export{s as default};
@@ -40,19 +40,19 @@ var _FrameTarget = class extends import_primitives.Transition {
40
40
  }
41
41
  async enter() {
42
42
  this.$log("enter");
43
- const { enterFrom: from, enterActive: active, enterTo: to, leaveTo } = this.$options;
43
+ const { enterFrom: from, enterActive: active, enterTo: to, leaveTo, enterKeep } = this.$options;
44
44
  const transitionStyles = { from, active, to };
45
45
  switch (this.$options.mode) {
46
46
  case "append":
47
47
  case "prepend":
48
48
  await Promise.all(Array.from(this.$el.children).filter((child) => from.split(" ").every((className) => child.classList.contains(className))).map((child) => {
49
- return (0, import_utils.transition)(child, transitionStyles);
49
+ return (0, import_utils.transition)(child, transitionStyles, enterKeep && "keep");
50
50
  }));
51
51
  break;
52
52
  case "replace":
53
53
  default:
54
54
  transitionStyles.from = Array.from(new Set([from, leaveTo].flat())).join(" ");
55
- await (0, import_utils.transition)(this.$el, transitionStyles);
55
+ await (0, import_utils.transition)(this.$el, transitionStyles, enterKeep && "keep");
56
56
  }
57
57
  }
58
58
  updateContent(newTarget) {
@@ -1 +1 @@
1
- import{transition as s}from"@studiometa/js-toolkit/utils";import{Transition as r}from"../../primitives/index.js";class o extends r{static config={...r.config,name:"FrameTarget",log:!0,options:{...r.config.options,mode:{type:String,default:"replace"},id:String}};static __INSERT_MODES={prepend:"afterbegin",append:"beforeend"};get $options(){const e=super.$options;return e.leaveKeep=!0,e}get id(){return this.$options.id??this.$el.id}async enter(){this.$log("enter");const{enterFrom:e,enterActive:t,enterTo:a,leaveTo:p}=this.$options,i={from:e,active:t,to:a};switch(this.$options.mode){case"append":case"prepend":await Promise.all(Array.from(this.$el.children).filter(n=>e.split(" ").every(l=>n.classList.contains(l))).map(n=>s(n,i)));break;case"replace":default:i.from=Array.from(new Set([e,p].flat())).join(" "),await s(this.$el,i)}}updateContent(e){switch(this.$options.mode){case"prepend":case"append":Array.from(e.$el.children).forEach(t=>{t.classList.add(...this.$options.enterFrom.split(" "))}),this.$el.insertAdjacentHTML(o.__INSERT_MODES[this.$options.mode],e.$el.innerHTML);break;case"replace":default:this.$el.innerHTML=e.$el.innerHTML;break}}}export{o as default};
1
+ import{transition as a}from"@studiometa/js-toolkit/utils";import{Transition as r}from"../../primitives/index.js";class o extends r{static config={...r.config,name:"FrameTarget",log:!0,options:{...r.config.options,mode:{type:String,default:"replace"},id:String}};static __INSERT_MODES={prepend:"afterbegin",append:"beforeend"};get $options(){const e=super.$options;return e.leaveKeep=!0,e}get id(){return this.$options.id??this.$el.id}async enter(){this.$log("enter");const{enterFrom:e,enterActive:t,enterTo:p,leaveTo:l,enterKeep:s}=this.$options,i={from:e,active:t,to:p};switch(this.$options.mode){case"append":case"prepend":await Promise.all(Array.from(this.$el.children).filter(n=>e.split(" ").every(c=>n.classList.contains(c))).map(n=>a(n,i,s&&"keep")));break;case"replace":default:i.from=Array.from(new Set([e,l].flat())).join(" "),await a(this.$el,i,s&&"keep")}}updateContent(e){switch(this.$options.mode){case"prepend":case"append":Array.from(e.$el.children).forEach(t=>{t.classList.add(...this.$options.enterFrom.split(" "))}),this.$el.insertAdjacentHTML(o.__INSERT_MODES[this.$options.mode],e.$el.innerHTML);break;case"replace":default:this.$el.innerHTML=e.$el.innerHTML;break}}}export{o as default};
@@ -0,0 +1,42 @@
1
+ {#
2
+ /**
3
+ * @file
4
+ * Image Grid.
5
+ *
6
+ * @param array<Figure> $images
7
+ * List of images to display. See Figure.twig for the composition of each image.
8
+ * @param array $attr
9
+ * Custom attributes for the root element.
10
+ * @param array $inner_attr
11
+ * Custom attributes for the inner element.
12
+ * @param array $image_attr
13
+ * Custom attributes for the images' elements.
14
+ */
15
+ #}
16
+
17
+ {% set attributes = merge_html_attributes(attr ?? null, { class: 'image-grid' }) %}
18
+ {% set inner_attributes =
19
+ merge_html_attributes(inner_attr ?? null, { class: 'image-grid__inner s:grid grid-cols-12 gap-10' })
20
+ %}
21
+
22
+ <div {{ html_attributes(attributes) }}>
23
+ <div {{ html_attributes(inner_attributes) }}>
24
+ {% for image in images %}
25
+ {% set modulo = loop.index % 5 %}
26
+ {% set image_attributes = merge_html_attributes(image_attr ?? null, {
27
+ class: 'image-grid__img'
28
+ }, {
29
+ class: {
30
+ 's:col-span-7': modulo == 1 or modulo == 4,
31
+ 's:col-span-5 mt-10': modulo == 2,
32
+ 's:col-span-5 mt-10 clear-m-left': modulo == 3 and not loop.last,
33
+ 's:col-start-2 s:col-end-11': modulo == 0 or (modulo in [0,3] and loop.last),
34
+ 's:col-start-2 s:col-end-13': loop.first and loop.last
35
+ }
36
+ }) %}
37
+ <div {{ html_attributes(image_attributes) }}>
38
+ {% include '@ui/atoms/Figure/Figure.twig' with image only %}
39
+ </div>
40
+ {% endfor %}
41
+ </div>
42
+ </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiometa/ui",
3
- "version": "0.2.5",
3
+ "version": "0.2.8",
4
4
  "description": "A set of opiniated, unstyled and accessible components",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "homepage": "https://github.com/studiometa/ui#readme",
31
31
  "dependencies": {
32
- "@studiometa/js-toolkit": "^2.0.0",
32
+ "@studiometa/js-toolkit": "^2.2.2",
33
33
  "deepmerge": "^4.2.2"
34
34
  }
35
35
  }