elvish-css 1.0.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 (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +518 -0
  3. package/dist/elvish.css +2194 -0
  4. package/dist/elvish.d.ts +78 -0
  5. package/dist/elvish.esm.js +2185 -0
  6. package/dist/elvish.iife.js +2169 -0
  7. package/dist/elvish.min.css +9 -0
  8. package/dist/elvish.umd.js +2173 -0
  9. package/elvish.css +28 -0
  10. package/elvish.js +81 -0
  11. package/global/global.css +16 -0
  12. package/global/modern.css +305 -0
  13. package/global/reset.css +507 -0
  14. package/global/tokens.css +154 -0
  15. package/global/transitions.css +288 -0
  16. package/global/transitions.js +289 -0
  17. package/global/utilities.css +151 -0
  18. package/package.json +61 -0
  19. package/primitives/adleithian/adleithian.css +16 -0
  20. package/primitives/adleithian/adleithian.js +63 -0
  21. package/primitives/bau/bau.css +86 -0
  22. package/primitives/bau/bau.js +127 -0
  23. package/primitives/enedh/enedh.css +38 -0
  24. package/primitives/enedh/enedh.js +110 -0
  25. package/primitives/esgal/esgal.css +39 -0
  26. package/primitives/esgal/esgal.js +115 -0
  27. package/primitives/fano/fano.css +28 -0
  28. package/primitives/fano/fano.js +108 -0
  29. package/primitives/gant-thala/gant-thala.css +32 -0
  30. package/primitives/gant-thala/gant-thala.js +69 -0
  31. package/primitives/glan-tholl/glan-tholl.css +71 -0
  32. package/primitives/glan-tholl/glan-tholl.js +147 -0
  33. package/primitives/glan-veleg/glan-veleg.css +45 -0
  34. package/primitives/glan-veleg/glan-veleg.js +138 -0
  35. package/primitives/gonath/gonath.css +57 -0
  36. package/primitives/gonath/gonath.js +113 -0
  37. package/primitives/gwistindor/gwistindor.css +52 -0
  38. package/primitives/gwistindor/gwistindor.js +96 -0
  39. package/primitives/hath/hath.css +39 -0
  40. package/primitives/hath/hath.js +107 -0
  41. package/primitives/him/him.css +43 -0
  42. package/primitives/him/him.js +169 -0
  43. package/primitives/miriant/miriant.css +75 -0
  44. package/primitives/miriant/miriant.js +158 -0
  45. package/primitives/thann/thann.css +57 -0
  46. package/primitives/thann/thann.js +96 -0
  47. package/primitives/tiniath/tiniath.css +16 -0
  48. package/primitives/tiniath/tiniath.js +88 -0
  49. package/primitives/vircantie/vircantie.css +24 -0
  50. package/primitives/vircantie/vircantie.js +83 -0
@@ -0,0 +1,138 @@
1
+ /**
2
+ * GlanVeleg Layout Custom Element
3
+ *
4
+ * A quantum layout with one fixed-width element and one fluid element.
5
+ *
6
+ * @property {string} side - Which side is the sidebar: "left" or "right" (default: left)
7
+ * @property {string} sideWidth - Width of sidebar when horizontal (default: 20rem)
8
+ * @property {string} contentMin - Min width of content before wrapping (default: 50%)
9
+ * @property {string} space - Gap between elements (default: var(--s1))
10
+ * @property {boolean} noStretch - Disable equal height (default: false)
11
+ *
12
+ * @example
13
+ * <i-glan-veleg side-width="15rem" content-min="60%">
14
+ * <nav>GlanVeleg content</nav>
15
+ * <main>Main content</main>
16
+ * </i-glan-veleg>
17
+ */
18
+
19
+ class GlanVelegLayout extends HTMLElement {
20
+ static get observedAttributes() {
21
+ return ['side', 'side-width', 'content-min', 'space', 'no-stretch'];
22
+ }
23
+
24
+ constructor() {
25
+ super();
26
+ this.render = this.render.bind(this);
27
+ }
28
+
29
+ connectedCallback() {
30
+ this.render();
31
+ }
32
+
33
+ attributeChangedCallback() {
34
+ this.render();
35
+ }
36
+
37
+ get side() {
38
+ return this.getAttribute('side') || 'left';
39
+ }
40
+
41
+ set side(val) {
42
+ this.setAttribute('side', val);
43
+ }
44
+
45
+ get sideWidth() {
46
+ return this.getAttribute('side-width') || '20rem';
47
+ }
48
+
49
+ set sideWidth(val) {
50
+ this.setAttribute('side-width', val);
51
+ }
52
+
53
+ get contentMin() {
54
+ return this.getAttribute('content-min') || '50%';
55
+ }
56
+
57
+ set contentMin(val) {
58
+ this.setAttribute('content-min', val);
59
+ }
60
+
61
+ get space() {
62
+ return this.getAttribute('space') || 'var(--s1)';
63
+ }
64
+
65
+ set space(val) {
66
+ this.setAttribute('space', val);
67
+ }
68
+
69
+ get noStretch() {
70
+ return this.hasAttribute('no-stretch');
71
+ }
72
+
73
+ set noStretch(val) {
74
+ if (val) {
75
+ this.setAttribute('no-stretch', '');
76
+ } else {
77
+ this.removeAttribute('no-stretch');
78
+ }
79
+ }
80
+
81
+ render() {
82
+ this.style.setProperty('--glan-veleg-width', this.sideWidth);
83
+ this.style.setProperty('--glan-veleg-content-min', this.contentMin);
84
+ this.style.setProperty('--glan-veleg-space', this.space);
85
+
86
+ const sideStr = this.side === 'right' ? '-right' : '-left';
87
+ const stretchStr = this.noStretch ? '-noStretch' : '';
88
+ const id = `GlanVeleg-${this.sideWidth}-${this.contentMin}-${this.space}${sideStr}${stretchStr}`.replace(/[^\w-]/g, '');
89
+
90
+ this.dataset.i = id;
91
+
92
+ if (!document.getElementById(id)) {
93
+ const styleEl = document.createElement('style');
94
+ styleEl.id = id;
95
+
96
+ const selector = `[data-i="${id}"]`;
97
+ let css = `${selector} { gap: ${this.space}; }`;
98
+
99
+ if (this.side === 'right') {
100
+ css += `
101
+ ${selector} > :first-child {
102
+ flex-basis: 0;
103
+ flex-grow: 999;
104
+ min-inline-size: ${this.contentMin};
105
+ }
106
+ ${selector} > :last-child {
107
+ flex-basis: ${this.sideWidth};
108
+ flex-grow: 1;
109
+ }
110
+ `;
111
+ } else {
112
+ css += `
113
+ ${selector} > :first-child {
114
+ flex-basis: ${this.sideWidth};
115
+ }
116
+ ${selector} > :last-child {
117
+ flex-basis: 0;
118
+ flex-grow: 999;
119
+ min-inline-size: ${this.contentMin};
120
+ }
121
+ `;
122
+ }
123
+
124
+ if (this.noStretch) {
125
+ css += `${selector} { align-items: flex-start; }`;
126
+ }
127
+
128
+ styleEl.textContent = css;
129
+ document.head.appendChild(styleEl);
130
+ }
131
+ }
132
+ }
133
+
134
+ if ('customElements' in window) {
135
+ customElements.define('i-glan-veleg', GlanVelegLayout);
136
+ }
137
+
138
+ export default GlanVelegLayout;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Gonath Layout (NEW)
3
+ *
4
+ * Pinterest-style layout where items pack efficiently into columns.
5
+ * Uses CSS columns as the primary method (widely supported).
6
+ * Progressively enhances to CSS Grid masonry where supported.
7
+ *
8
+ * CAVEATS:
9
+ * - CSS columns: items flow top-to-bottom, then left-to-right
10
+ * (not strictly "visual order" like true masonry)
11
+ * - CSS Grid masonry: experimental, limited browser support
12
+ */
13
+
14
+ i-gonath {
15
+ display: block;
16
+
17
+ /* CSS Columns approach (fallback) */
18
+ column-count: var(--gonath-columns, 3);
19
+ column-gap: var(--gonath-space, var(--s1));
20
+ }
21
+
22
+ i-gonath > * {
23
+ /* Prevent items from breaking across columns */
24
+ break-inside: avoid;
25
+
26
+ /* Add vertical spacing between items */
27
+ margin-block-end: var(--gonath-space, var(--s1));
28
+ }
29
+
30
+ /* Progressive enhancement: CSS Grid masonry where supported */
31
+ @supports (grid-template-rows: masonry) {
32
+ i-gonath {
33
+ display: grid;
34
+ column-count: unset;
35
+ grid-template-columns: repeat(var(--gonath-columns, 3), 1fr);
36
+ grid-template-rows: masonry;
37
+ gap: var(--gonath-space, var(--s1));
38
+ }
39
+
40
+ i-gonath > * {
41
+ margin-block-end: 0;
42
+ break-inside: unset;
43
+ }
44
+ }
45
+
46
+ /* Responsive column counts */
47
+ @media (max-width: 800px) {
48
+ i-gonath {
49
+ --gonath-columns: 2;
50
+ }
51
+ }
52
+
53
+ @media (max-width: 500px) {
54
+ i-gonath {
55
+ --gonath-columns: 1;
56
+ }
57
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Gonath Layout Custom Element (NEW)
3
+ *
4
+ * Pinterest-style layout with efficient column packing.
5
+ *
6
+ * Uses CSS columns (widely supported) with progressive enhancement
7
+ * to CSS Grid masonry where available.
8
+ *
9
+ * @property {number} columns - Number of columns (default: 3)
10
+ * @property {string} space - Gap between items (default: var(--s1))
11
+ *
12
+ * NOTE: CSS columns flow top-to-bottom, then left-to-right.
13
+ * This means visual order differs from DOM order.
14
+ * For true masonry ordering, JavaScript is required.
15
+ *
16
+ * @example
17
+ * <i-gonath columns="4" space="var(--s2)">
18
+ * <div>Item 1</div>
19
+ * <div>Taller Item 2</div>
20
+ * <div>Item 3</div>
21
+ * ...
22
+ * </i-gonath>
23
+ */
24
+
25
+ class GonathLayout extends HTMLElement {
26
+ static get observedAttributes() {
27
+ return ['columns', 'space'];
28
+ }
29
+
30
+ constructor() {
31
+ super();
32
+ this.render = this.render.bind(this);
33
+ }
34
+
35
+ connectedCallback() {
36
+ this.render();
37
+ }
38
+
39
+ attributeChangedCallback() {
40
+ this.render();
41
+ }
42
+
43
+ get columns() {
44
+ return parseInt(this.getAttribute('columns'), 10) || 3;
45
+ }
46
+
47
+ set columns(val) {
48
+ this.setAttribute('columns', val);
49
+ }
50
+
51
+ get space() {
52
+ return this.getAttribute('space') || 'var(--s1)';
53
+ }
54
+
55
+ set space(val) {
56
+ this.setAttribute('space', val);
57
+ }
58
+
59
+ // Check if CSS Grid masonry is supported
60
+ static get isGridGonathSupported() {
61
+ return CSS.supports('grid-template-rows', 'masonry');
62
+ }
63
+
64
+ render() {
65
+ this.style.setProperty('--gonath-columns', this.columns);
66
+ this.style.setProperty('--gonath-space', this.space);
67
+
68
+ const id = `Gonath-${this.columns}-${this.space}`.replace(/[^\w-]/g, '');
69
+ this.dataset.i = id;
70
+
71
+ if (!document.getElementById(id)) {
72
+ const styleEl = document.createElement('style');
73
+ styleEl.id = id;
74
+
75
+ const selector = `[data-i="${id}"]`;
76
+
77
+ let css = `
78
+ ${selector} {
79
+ column-count: ${this.columns};
80
+ column-gap: ${this.space};
81
+ }
82
+ ${selector} > * {
83
+ margin-block-end: ${this.space};
84
+ }
85
+ `;
86
+
87
+ // Progressive enhancement for CSS Grid masonry
88
+ css += `
89
+ @supports (grid-template-rows: masonry) {
90
+ ${selector} {
91
+ display: grid;
92
+ column-count: unset;
93
+ grid-template-columns: repeat(${this.columns}, 1fr);
94
+ grid-template-rows: masonry;
95
+ gap: ${this.space};
96
+ }
97
+ ${selector} > * {
98
+ margin-block-end: 0;
99
+ }
100
+ }
101
+ `;
102
+
103
+ styleEl.textContent = css;
104
+ document.head.appendChild(styleEl);
105
+ }
106
+ }
107
+ }
108
+
109
+ if ('customElements' in window) {
110
+ customElements.define('i-gonath', GonathLayout);
111
+ }
112
+
113
+ export default GonathLayout;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Switcher Layout
3
+ *
4
+ * Switches directly between horizontal and vertical layouts
5
+ * at a container-based threshold. No intermediary states.
6
+ *
7
+ * Uses the "Holy Albatross" technique.
8
+ */
9
+
10
+ i-gwistindor {
11
+ display: flex;
12
+ flex-wrap: wrap;
13
+ gap: var(--gwistindor-space, var(--s1));
14
+ }
15
+
16
+ i-gwistindor > * {
17
+ flex-grow: 1;
18
+ /*
19
+ * The magic: produces huge positive (vertical) or negative (horizontal) values.
20
+ * Default: --layout-threshold-md (45rem ≈ 720px) - switches at tablet width.
21
+ * NOTE: This is a *layout* threshold, not a text measure!
22
+ */
23
+ flex-basis: calc((var(--gwistindor-threshold, var(--layout-threshold-md, 45rem)) - 100%) * 999);
24
+ }
25
+
26
+ /* Quantity query: force vertical if more than threshold items */
27
+ i-gwistindor[limit="2"] > :nth-last-child(n+3),
28
+ i-gwistindor[limit="2"] > :nth-last-child(n+3) ~ * {
29
+ flex-basis: 100%;
30
+ }
31
+
32
+ i-gwistindor[limit="3"] > :nth-last-child(n+4),
33
+ i-gwistindor[limit="3"] > :nth-last-child(n+4) ~ * {
34
+ flex-basis: 100%;
35
+ }
36
+
37
+ i-gwistindor:not([limit]) > :nth-last-child(n+5),
38
+ i-gwistindor:not([limit]) > :nth-last-child(n+5) ~ *,
39
+ i-gwistindor[limit="4"] > :nth-last-child(n+5),
40
+ i-gwistindor[limit="4"] > :nth-last-child(n+5) ~ * {
41
+ flex-basis: 100%;
42
+ }
43
+
44
+ i-gwistindor[limit="5"] > :nth-last-child(n+6),
45
+ i-gwistindor[limit="5"] > :nth-last-child(n+6) ~ * {
46
+ flex-basis: 100%;
47
+ }
48
+
49
+ i-gwistindor[limit="6"] > :nth-last-child(n+7),
50
+ i-gwistindor[limit="6"] > :nth-last-child(n+7) ~ * {
51
+ flex-basis: 100%;
52
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Switcher Layout Custom Element
3
+ *
4
+ * Switches between horizontal and vertical at a container threshold.
5
+ * Uses the "Holy Albatross" technique - no intermediary states.
6
+ *
7
+ * @property {string} threshold - Container width to switch at (default: var(--measure))
8
+ * @property {string} space - Gap between elements (default: var(--s1))
9
+ * @property {number} limit - Max items for horizontal layout (default: 4)
10
+ *
11
+ * @example
12
+ * <i-gwistindor threshold="30rem" limit="3">
13
+ * <div>One</div>
14
+ * <div>Two</div>
15
+ * <div>Three</div>
16
+ * </i-gwistindor>
17
+ */
18
+
19
+ class GwistindorLayout extends HTMLElement {
20
+ static get observedAttributes() {
21
+ return ['threshold', 'space', 'limit'];
22
+ }
23
+
24
+ constructor() {
25
+ super();
26
+ this.render = this.render.bind(this);
27
+ }
28
+
29
+ connectedCallback() {
30
+ this.render();
31
+ }
32
+
33
+ attributeChangedCallback() {
34
+ this.render();
35
+ }
36
+
37
+ get threshold() {
38
+ return this.getAttribute('threshold') || 'var(--measure)';
39
+ }
40
+
41
+ set threshold(val) {
42
+ this.setAttribute('threshold', val);
43
+ }
44
+
45
+ get space() {
46
+ return this.getAttribute('space') || 'var(--s1)';
47
+ }
48
+
49
+ set space(val) {
50
+ this.setAttribute('space', val);
51
+ }
52
+
53
+ get limit() {
54
+ return parseInt(this.getAttribute('limit'), 10) || 4;
55
+ }
56
+
57
+ set limit(val) {
58
+ this.setAttribute('limit', val);
59
+ }
60
+
61
+ render() {
62
+ this.style.setProperty('--gwistindor-threshold', this.threshold);
63
+ this.style.setProperty('--gwistindor-space', this.space);
64
+
65
+ const id = `Gwistindor-${this.threshold}-${this.space}-${this.limit}`.replace(/[^\w-]/g, '');
66
+ this.dataset.i = id;
67
+
68
+ if (!document.getElementById(id)) {
69
+ const styleEl = document.createElement('style');
70
+ styleEl.id = id;
71
+
72
+ const selector = `[data-i="${id}"]`;
73
+ const limitPlusOne = this.limit + 1;
74
+
75
+ styleEl.textContent = `
76
+ ${selector} {
77
+ gap: ${this.space};
78
+ }
79
+ ${selector} > * {
80
+ flex-basis: calc((${this.threshold} - 100%) * 999);
81
+ }
82
+ ${selector} > :nth-last-child(n+${limitPlusOne}),
83
+ ${selector} > :nth-last-child(n+${limitPlusOne}) ~ * {
84
+ flex-basis: 100%;
85
+ }
86
+ `;
87
+ document.head.appendChild(styleEl);
88
+ }
89
+ }
90
+ }
91
+
92
+ if ('customElements' in window) {
93
+ customElements.define('i-gwistindor', GwistindorLayout);
94
+ }
95
+
96
+ export default GwistindorLayout;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Stack Layout
3
+ *
4
+ * Injects vertical margin between successive child elements.
5
+ * The foundation of vertical rhythm.
6
+ */
7
+
8
+ i-hath {
9
+ display: flex;
10
+ flex-direction: column;
11
+ justify-content: flex-start;
12
+ }
13
+
14
+ i-hath > * {
15
+ /* Remove any existing vertical margins */
16
+ margin-block: 0;
17
+ }
18
+
19
+ i-hath > * + * {
20
+ /* Apply margin only between successive elements */
21
+ margin-block-start: var(--hath-space, var(--s1));
22
+ }
23
+
24
+ /* Recursive variant - applies to all descendants */
25
+ i-hath[recursive] * + * {
26
+ margin-block-start: var(--hath-space, var(--s1));
27
+ }
28
+
29
+ /* Split variant - pushes element and siblings after it to the bottom */
30
+ i-hath[split-after="1"] > :nth-child(1) { margin-block-end: auto; }
31
+ i-hath[split-after="2"] > :nth-child(2) { margin-block-end: auto; }
32
+ i-hath[split-after="3"] > :nth-child(3) { margin-block-end: auto; }
33
+ i-hath[split-after="4"] > :nth-child(4) { margin-block-end: auto; }
34
+ i-hath[split-after="5"] > :nth-child(5) { margin-block-end: auto; }
35
+
36
+ /* When Stack needs to fill its parent */
37
+ i-hath:only-child {
38
+ block-size: 100%;
39
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Stack Layout Custom Element
3
+ *
4
+ * Injects vertical margin between successive child elements.
5
+ *
6
+ * @property {string} space - A CSS margin value (default: var(--s1))
7
+ * @property {boolean} recursive - Apply to all descendants, not just children
8
+ * @property {number} splitAfter - Element index after which to split with auto margin
9
+ *
10
+ * @example
11
+ * <i-hath space="var(--s2)">
12
+ * <h2>Heading</h2>
13
+ * <p>Paragraph one</p>
14
+ * <p>Paragraph two</p>
15
+ * </i-hath>
16
+ */
17
+
18
+ class HathLayout extends HTMLElement {
19
+ static get observedAttributes() {
20
+ return ['space', 'recursive', 'split-after'];
21
+ }
22
+
23
+ constructor() {
24
+ super();
25
+ this.render = this.render.bind(this);
26
+ }
27
+
28
+ connectedCallback() {
29
+ this.render();
30
+ }
31
+
32
+ attributeChangedCallback() {
33
+ this.render();
34
+ }
35
+
36
+ get space() {
37
+ return this.getAttribute('space') || 'var(--s1)';
38
+ }
39
+
40
+ set space(val) {
41
+ this.setAttribute('space', val);
42
+ }
43
+
44
+ get recursive() {
45
+ return this.hasAttribute('recursive');
46
+ }
47
+
48
+ set recursive(val) {
49
+ if (val) {
50
+ this.setAttribute('recursive', '');
51
+ } else {
52
+ this.removeAttribute('recursive');
53
+ }
54
+ }
55
+
56
+ get splitAfter() {
57
+ const val = this.getAttribute('split-after');
58
+ return val ? parseInt(val, 10) : null;
59
+ }
60
+
61
+ set splitAfter(val) {
62
+ if (val) {
63
+ this.setAttribute('split-after', val);
64
+ } else {
65
+ this.removeAttribute('split-after');
66
+ }
67
+ }
68
+
69
+ render() {
70
+ // Generate unique identifier for this configuration
71
+ const recursive = this.recursive ? '-recursive' : '';
72
+ const split = this.splitAfter ? `-split${this.splitAfter}` : '';
73
+ const id = `Hath-${this.space}${recursive}${split}`.replace(/[^\w-]/g, '');
74
+
75
+ this.dataset.i = id;
76
+ this.style.setProperty('--hath-space', this.space);
77
+
78
+ // Check if styles already exist for this configuration
79
+ if (!document.getElementById(id)) {
80
+ const styleEl = document.createElement('style');
81
+ styleEl.id = id;
82
+
83
+ const selector = `[data-i="${id}"]`;
84
+ let css = '';
85
+
86
+ if (this.recursive) {
87
+ css = `${selector} * + * { margin-block-start: ${this.space}; }`;
88
+ } else {
89
+ css = `${selector} > * + * { margin-block-start: ${this.space}; }`;
90
+ }
91
+
92
+ if (this.splitAfter) {
93
+ css += `${selector} > :nth-child(${this.splitAfter}) { margin-block-end: auto; }`;
94
+ }
95
+
96
+ styleEl.textContent = css;
97
+ document.head.appendChild(styleEl);
98
+ }
99
+ }
100
+ }
101
+
102
+ // Define the custom element
103
+ if ('customElements' in window) {
104
+ customElements.define('i-hath', HathLayout);
105
+ }
106
+
107
+ export default HathLayout;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Him Layout (NEW)
3
+ *
4
+ * Creates sticky positioning with configurable offset.
5
+ * Solves the common pattern of sticky headers/sidebars.
6
+ *
7
+ * IMPORTANT: The parent must have defined height or be
8
+ * in a scroll context for sticky to work properly.
9
+ */
10
+
11
+ i-him {
12
+ display: block;
13
+ position: sticky;
14
+
15
+ /* Default: stick to top */
16
+ inset-block-start: var(--him-offset, 0);
17
+
18
+ /* Ensure it stays above sibling content when stuck */
19
+ z-index: var(--him-z, 1);
20
+ }
21
+
22
+ /* Stick to bottom instead */
23
+ i-him[to="bottom"] {
24
+ inset-block-start: auto;
25
+ inset-block-end: var(--him-offset, 0);
26
+ }
27
+
28
+ /* Stick to left (in horizontal scroll context) */
29
+ i-him[to="left"] {
30
+ inset-block-start: auto;
31
+ inset-inline-start: var(--him-offset, 0);
32
+ }
33
+
34
+ /* Stick to right (in horizontal scroll context) */
35
+ i-him[to="right"] {
36
+ inset-block-start: auto;
37
+ inset-inline-end: var(--him-offset, 0);
38
+ }
39
+
40
+ /* Sentinel for detecting stuck state (JavaScript enhancement) */
41
+ i-him[data-stuck="true"] {
42
+ /* Add styles here or use this selector in your own CSS */
43
+ }