ds-one 0.2.5-alpha.12 → 0.2.5-alpha.14

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.
@@ -104,6 +104,10 @@ export function initDeviceDetection(): DeviceInfo {
104
104
  scalingFactor.toFixed(3)
105
105
  );
106
106
 
107
+ // Add .mobile class to html element for CSS targeting
108
+ document.documentElement.classList.add("mobile");
109
+ document.documentElement.classList.remove("desktop");
110
+
107
111
  console.log(
108
112
  `[DS one] Mobile device detected - ${deviceInfo.deviceType} (${deviceInfo.screenWidth}x${deviceInfo.screenHeight}), scaling factor: ${scalingFactor.toFixed(2)}`
109
113
  );
@@ -113,6 +117,10 @@ export function initDeviceDetection(): DeviceInfo {
113
117
  document.documentElement.style.setProperty("--sf", "1");
114
118
  // Also set --sf for backwards compatibility
115
119
  document.documentElement.style.setProperty("--sf", "1");
120
+
121
+ // Add .desktop class and remove .mobile class
122
+ document.documentElement.classList.add("desktop");
123
+ document.documentElement.classList.remove("mobile");
116
124
  }
117
125
  console.log(
118
126
  `[DS one] Desktop device detected (${deviceInfo.screenWidth}x${deviceInfo.screenHeight})`
@@ -1,4 +1,4 @@
1
- /* version 0.2.5-alpha.12 */
1
+ /* version 0.2.5-alpha.14 */
2
2
 
3
3
  @import url("https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@200");
4
4
 
@@ -28,7 +28,7 @@ input {
28
28
 
29
29
  --black: #2a2a2a;
30
30
  --white: rgb(255 255 255);
31
- --slate: #bdbdbd;
31
+ --slate: #1e1e1e;
32
32
  --slate-light: #e6e6e6;
33
33
  --slate-dark: #3c3c3c;
34
34
 
@@ -43,6 +43,8 @@ input {
43
43
  --yellow: #eaff00;
44
44
  --orange: #fec20d;
45
45
 
46
+ --accent-color: var(--apple-green);
47
+
46
48
  /* 4-page component colors */
47
49
 
48
50
  /* ds-grid color */
@@ -54,9 +56,14 @@ input {
54
56
  --typeface-regular: "GT-America-Standard-Regular";
55
57
  --typeface-medium: "GT-America-Standard-Medium";
56
58
  --typeface-compressed: "GT-America-Compressed-Regular";
57
- --typeface-regular-jp: "Noto Sans JP";
58
59
  --typeface-mono: "Iosevka";
59
60
 
61
+ /* language specific typefaces */
62
+
63
+ --typeface-regular-jp: "Noto Sans JP";
64
+
65
+ /* typefaces sizes and weight */
66
+
60
67
  --type-size-default: calc(14px * var(--sf));
61
68
  --type-size-small: calc(10px * var(--sf));
62
69
  --type-weight-default: 500;
@@ -73,6 +80,37 @@ input {
73
80
  --type-weight-book: 400;
74
81
  --type-lineheight-book: 15px;
75
82
 
83
+ /* ----------------------------------------------------------
84
+ SIZING SCALE
85
+ - Define a base unit ( --1 ) and derive all other sizes
86
+ - Larger sizes are simple multipliers (×2, ×3, ×4)
87
+ - Smaller sizes use fractional multipliers (0.1, 0.25, 0.8)
88
+ ---------------------------------------------------------- */
89
+
90
+ --01: calc(var(--1) * 0.1);
91
+ --025: calc(var(--1) * 0.25);
92
+ --05: calc(var(--1) * 0.5);
93
+ --08: calc(var(--1) * 0.8);
94
+ --1: 20px; /* SET BASE UNIT HERE FOR EXAMPLE 20px */
95
+ --2: calc(var(--1) * 2);
96
+ --3: calc(var(--1) * 3);
97
+ --4: calc(var(--1) * 4);
98
+ --8: calc(var(--1) * 8);
99
+ --12: calc(var(--1) * 12);
100
+
101
+ /* Semantic sizing units */
102
+
103
+ --tenth: var(--01);
104
+ --quarter: var(--025);
105
+ --half: var(--05);
106
+ --eight-tenth: var(--08);
107
+ --unit: var(--1);
108
+ --double: var(--2);
109
+ --triple: var(--3);
110
+ --quad: var(--4);
111
+ --oct: var(--8);
112
+ --dozen: var(--12);
113
+
76
114
  /* size */
77
115
  --outline-stroke: 1px solid light-dark(var(--black), var(--slate-dark));
78
116
  --outline-stroke-mobile: calc(1px * var(--sf)) solid
@@ -81,20 +119,6 @@ input {
81
119
  --item-height: calc(19px * var(--sf));
82
120
  --margin-correction: calc(1px * var(--sf));
83
121
 
84
- /* SIZING */
85
-
86
- /* main unit */
87
- --1: 20px;
88
- /* bigger sizes */
89
- --2: calc(var(--1) * 2);
90
- --3: calc(var(--1) * 3);
91
- --4: calc(var(--1) * 4);
92
-
93
- /* smaller sizes */
94
- --01: calc(var(--1) * 0.1);
95
- --025: calc(var(--1) * 0.25);
96
- --08: calc(var(--1) * 0.8);
97
-
98
122
  /* button */
99
123
  --button-background-color-primary: var(--accent-color);
100
124
  --button-background-color-secondary: light-dark(
@@ -1,3 +1,196 @@
1
1
  // ds-banner.ts
2
- // Core component
2
+ // Fixed banner component for notifications/alerts
3
3
 
4
+ import { LitElement, html, css } from "lit";
5
+ import { getText } from "../0-face/i18n.js";
6
+ import "./ds-text.js";
7
+ import "./ds-button.js";
8
+
9
+ declare global {
10
+ interface CustomElementRegistry {
11
+ define(name: string, constructor: typeof LitElement): void;
12
+ }
13
+ var customElements: CustomElementRegistry;
14
+ }
15
+
16
+ export class Banner extends LitElement {
17
+ static properties = {
18
+ textKey: { type: String, attribute: "text-key" },
19
+ actionKey: { type: String, attribute: "action-key" },
20
+ href: { type: String },
21
+ mailto: { type: String },
22
+ subjectKey: { type: String, attribute: "subject-key" },
23
+ describeKey: { type: String, attribute: "describe-key" },
24
+ appVersionKey: { type: String, attribute: "app-version-key" },
25
+ variant: { type: String },
26
+ version: { type: String },
27
+ _showVersion: { type: Boolean, state: true },
28
+ };
29
+
30
+ textKey: string = "";
31
+ actionKey: string = "";
32
+ href: string = "";
33
+ mailto: string = "";
34
+ subjectKey: string = "";
35
+ describeKey: string = "";
36
+ appVersionKey: string = "";
37
+ variant: string = "warning"; // warning, info, success, error
38
+ version: string = "";
39
+ _showVersion: boolean = false;
40
+
41
+ private _boundUpdate = () => this.requestUpdate();
42
+
43
+ connectedCallback() {
44
+ super.connectedCallback();
45
+ // Listen for translations and language changes to rebuild mailto URL
46
+ window.addEventListener("translations-loaded", this._boundUpdate);
47
+ window.addEventListener("language-changed", this._boundUpdate);
48
+ }
49
+
50
+ disconnectedCallback() {
51
+ super.disconnectedCallback();
52
+ window.removeEventListener("translations-loaded", this._boundUpdate);
53
+ window.removeEventListener("language-changed", this._boundUpdate);
54
+ }
55
+
56
+ static styles = css`
57
+ :host {
58
+ display: flex;
59
+ position: absolute;
60
+ top: 0;
61
+ left: 0;
62
+ right: 0;
63
+ width: 100%;
64
+ height: calc(var(--unit) * var(--sf, 1));
65
+ align-items: center;
66
+ justify-content: space-between;
67
+ padding: 0 calc(var(--unit) * var(--sf, 1));
68
+ box-sizing: border-box;
69
+ z-index: 9999;
70
+ }
71
+
72
+ :host([variant="warning"]) {
73
+ background-color: color-mix(in srgb, var(--yellow) 50%, transparent);
74
+ --banner-text-color: color-mix(in srgb, var(--black) 50%, transparent);
75
+ --banner-action-color: var(--slate);
76
+ }
77
+
78
+ :host([variant="info"]) {
79
+ background-color: rgba(var(--sharp-blue-rgb, 0, 122, 255), 0.7);
80
+ --banner-text-color: var(--white, #fff);
81
+ --banner-action-color: var(--white, #fff);
82
+ }
83
+
84
+ :host([variant="success"]) {
85
+ background-color: rgba(var(--apple-green-rgb, 52, 199, 89), 0.7);
86
+ --banner-text-color: var(--white, #fff);
87
+ --banner-action-color: var(--white, #fff);
88
+ }
89
+
90
+ :host([variant="error"]) {
91
+ background-color: rgba(var(--tuned-red-rgb, 255, 59, 48), 0.7);
92
+ --banner-text-color: var(--white, #fff);
93
+ --banner-action-color: var(--slate, #1e1e1e);
94
+ }
95
+
96
+ .text-wrapper {
97
+ flex: 1;
98
+ cursor: pointer;
99
+ user-select: none;
100
+ }
101
+
102
+ .text-wrapper ds-text,
103
+ .text-wrapper .version {
104
+ color: var(--banner-text-color);
105
+ }
106
+
107
+ .action-wrapper {
108
+ font-size: calc(12px * var(--sf, 1));
109
+ }
110
+
111
+ .action-wrapper a {
112
+ color: var(--banner-action-color);
113
+ text-decoration: none;
114
+ font-family: var(--typeface-regular);
115
+ font-size: calc(12px * var(--sf, 1));
116
+ cursor: pointer;
117
+ pointer-events: auto;
118
+ display: inline-block;
119
+ }
120
+
121
+ .action-wrapper a:hover {
122
+ opacity: 0.8;
123
+ }
124
+
125
+ .action-wrapper ds-text {
126
+ color: var(--banner-action-color);
127
+ font-family: var(--typeface-regular);
128
+ font-size: calc(12px * var(--sf, 1));
129
+ pointer-events: none;
130
+ }
131
+ `;
132
+
133
+ private _toggleVersion() {
134
+ if (this.version) {
135
+ this._showVersion = !this._showVersion;
136
+ }
137
+ }
138
+
139
+ private _getMailtoHref(): string {
140
+ // If a direct href is provided, use it
141
+ if (this.href && this.href !== "#") return this.href;
142
+
143
+ // If mailto is provided, build internationalized URL
144
+ if (this.mailto) {
145
+ try {
146
+ const subject = this.subjectKey
147
+ ? getText(this.subjectKey) || this.subjectKey
148
+ : "Issue report";
149
+ const describe = this.describeKey
150
+ ? getText(this.describeKey) || this.describeKey
151
+ : "Describe the issue:";
152
+ const appVersionLabel = this.appVersionKey
153
+ ? getText(this.appVersionKey) || this.appVersionKey
154
+ : "App version:";
155
+
156
+ const body = `${describe}\n\n\n${appVersionLabel} ${this.version || ""}`;
157
+
158
+ return `mailto:${this.mailto}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
159
+ } catch (error) {
160
+ // Fallback if translations fail
161
+ return `mailto:${this.mailto}?subject=Issue%20report&body=Describe%20the%20issue%3A%0A%0A%0AApp%20version%3A%20${this.version || ""}`;
162
+ }
163
+ }
164
+
165
+ return "#";
166
+ }
167
+
168
+ render() {
169
+ const mailtoHref = this._getMailtoHref();
170
+
171
+ return html`
172
+ <div class="text-wrapper" @click=${this._toggleVersion}>
173
+ ${this._showVersion && this.version
174
+ ? html`<ds-text default-value=${this.version}></ds-text>`
175
+ : html`<ds-text key=${this.textKey}><slot></slot></ds-text>`}
176
+ </div>
177
+ ${this.actionKey
178
+ ? html`
179
+ <div class="action-wrapper">
180
+ <a href=${mailtoHref}>
181
+ <ds-text key=${this.actionKey}></ds-text>
182
+ </a>
183
+ </div>
184
+ `
185
+ : ""}
186
+ `;
187
+ }
188
+ }
189
+
190
+ customElements.define("ds-banner", Banner);
191
+
192
+ declare global {
193
+ interface HTMLElementTagNameMap {
194
+ "ds-banner": Banner;
195
+ }
196
+ }
@@ -56,10 +56,11 @@ export class Button extends LitElement {
56
56
  static styles = css`
57
57
  button {
58
58
  max-height: calc(var(--08) * var(--sf));
59
- border: none;
59
+ display: inline-flex;
60
+ align-items: center;
61
+ justify-content: center;
60
62
  cursor: pointer;
61
- font-size: calc(var(--type-size-default) * var(--sf));
62
- padding: 0 calc(1px * var(--sf));
63
+ padding: 0 calc(0.5px * var(--sf));
63
64
  color: var(--button-text-color);
64
65
  font-family: var(--typeface-regular);
65
66
  }
@@ -82,6 +83,19 @@ export class Button extends LitElement {
82
83
  font-family: var(--typeface-regular);
83
84
  }
84
85
 
86
+ button.text {
87
+ background-color: transparent;
88
+ color: var(--button-color, var(--button-text-color));
89
+ font-family: var(--typeface-regular);
90
+ padding: 0;
91
+ text-decoration: none;
92
+ }
93
+
94
+ button.text:hover {
95
+ opacity: 0.8;
96
+ text-decoration: none;
97
+ }
98
+
85
99
  button[bold] {
86
100
  font-weight: var(--type-weight-bold);
87
101
  font-family: var(--typeface-medium);
@@ -50,7 +50,7 @@ export class Text extends LitElement {
50
50
  :host {
51
51
  display: inline;
52
52
  font-family: var(--typeface-regular);
53
- font-size: calc(var(--type-size-default) * var(--sf));
53
+ font-size: var(--type-size-default);
54
54
  font-weight: var(--type-weight-default);
55
55
  line-height: calc(var(--type-lineheight-default) * var(--sf));
56
56
  letter-spacing: calc(var(--type-letterspacing-default) * var(--sf));
@@ -0,0 +1,60 @@
1
+ // ds-container.ts
2
+ // Container component with responsive width constraints
3
+
4
+ import { LitElement, html, css } from "lit";
5
+
6
+ declare global {
7
+ interface CustomElementRegistry {
8
+ define(name: string, constructor: typeof LitElement): void;
9
+ }
10
+ var customElements: CustomElementRegistry;
11
+ }
12
+
13
+ export class Container extends LitElement {
14
+ static styles = css`
15
+ :host {
16
+ display: flex;
17
+ width: 100%;
18
+ max-width: 100%;
19
+ flex-direction: column;
20
+ background-color: var(--background-color);
21
+ box-sizing: border-box;
22
+ }
23
+
24
+ /* Ensure children don't overflow */
25
+ :host ::slotted(*) {
26
+ max-width: 100%;
27
+ box-sizing: border-box;
28
+ }
29
+
30
+ /* Mobile: 100% width */
31
+ @media (max-width: 820px) {
32
+ :host {
33
+ width: 100%;
34
+ max-width: 100%;
35
+ }
36
+ }
37
+
38
+ /* Desktop: max-width 1000px, centered */
39
+ @media (min-width: 821px) {
40
+ :host {
41
+ max-width: 1000px;
42
+ margin-left: auto;
43
+ margin-right: auto;
44
+ width: 100%;
45
+ }
46
+ }
47
+ `;
48
+
49
+ render() {
50
+ return html`<slot></slot>`;
51
+ }
52
+ }
53
+
54
+ customElements.define("ds-container", Container);
55
+
56
+ declare global {
57
+ interface HTMLElementTagNameMap {
58
+ "ds-container": Container;
59
+ }
60
+ }
@@ -2,6 +2,7 @@
2
2
  // Simple grid layout component
3
3
 
4
4
  import { LitElement, html, css } from "lit";
5
+ import { detectMobileDevice } from "../0-face/device";
5
6
 
6
7
  declare global {
7
8
  interface CustomElementRegistry {
@@ -16,6 +17,8 @@ export class Grid extends LitElement {
16
17
  };
17
18
 
18
19
  align?: string;
20
+ private resizeObserver?: () => void;
21
+ private resizeTimeout?: any;
19
22
 
20
23
  static styles = css`
21
24
  :host {
@@ -23,13 +26,13 @@ export class Grid extends LitElement {
23
26
  margin-left: 0.5px !important;
24
27
  display: grid;
25
28
  width: 1440px;
26
- height: 360px;
29
+ height: 1280px;
27
30
  grid-template-columns: repeat(auto-fill, 19px);
28
31
  grid-template-rows: repeat(auto-fill, 19px);
29
32
  gap: 1px;
30
33
  row-rule: calc(1px * var(--sf)) solid var(--grid-color);
31
34
  column-rule: calc(1px * var(--sf)) solid var(--grid-color);
32
- outline: 1px solid black;
35
+ outline: calc(1px * var(--sf)) solid var(--yellow);
33
36
  position: fixed;
34
37
  top: 0;
35
38
  left: 50%;
@@ -42,7 +45,7 @@ export class Grid extends LitElement {
42
45
  :host(.mobile) {
43
46
  width: calc(100% - calc(1px * var(--sf)));
44
47
  max-width: 100vw;
45
- margin-left: 0 !important;
48
+ margin-left: 0.5px !important;
46
49
  margin-top: 0 !important;
47
50
  box-sizing: border-box;
48
51
  position: fixed;
@@ -73,6 +76,43 @@ export class Grid extends LitElement {
73
76
  }
74
77
  `;
75
78
 
79
+ connectedCallback() {
80
+ super.connectedCallback();
81
+ this.updateMobileClass();
82
+
83
+ // Listen for resize events to update mobile class
84
+ this.resizeObserver = () => {
85
+ if (this.resizeTimeout) {
86
+ clearTimeout(this.resizeTimeout);
87
+ }
88
+ this.resizeTimeout = setTimeout(() => {
89
+ this.updateMobileClass();
90
+ }, 100);
91
+ };
92
+ window.addEventListener("resize", this.resizeObserver);
93
+ }
94
+
95
+ disconnectedCallback() {
96
+ super.disconnectedCallback();
97
+ if (this.resizeObserver) {
98
+ window.removeEventListener("resize", this.resizeObserver);
99
+ }
100
+ if (this.resizeTimeout) {
101
+ clearTimeout(this.resizeTimeout);
102
+ }
103
+ }
104
+
105
+ private updateMobileClass() {
106
+ const isMobile = detectMobileDevice();
107
+ if (isMobile) {
108
+ this.classList.add("mobile");
109
+ this.classList.remove("desktop");
110
+ } else {
111
+ this.classList.add("desktop");
112
+ this.classList.remove("mobile");
113
+ }
114
+ }
115
+
76
116
  render() {
77
117
  return html``;
78
118
  }