exsdk-ui5 0.1.3 → 0.1.5

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/README.md CHANGED
@@ -34,7 +34,7 @@ await ExCore.init({ licenseKey: "YOUR_KEY" });
34
34
  ```xml
35
35
  <!-- View XML -->
36
36
  <mvc:View
37
- xmlns:ex="exsdk.controls">
37
+ xmlns:ex="project1.control">
38
38
  <ex:ExTable id="myTable" title="Ürünler" columns="{/columns}" rows="{/rows}" />
39
39
  <ex:ExButton text="Kaydet" type="primary" press=".onSave" />
40
40
  </mvc:View>
package/copy-exsdk.cjs ADDED
@@ -0,0 +1,36 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ const root = process.cwd();
5
+ const src = path.join(root, "node_modules", "exsdk-ui5", "src", "controls");
6
+ const dest = path.join(root, "webapp", "control");
7
+ const css = path.join(root, "node_modules", "exsdk-ui5", "dist", "exsdk.ui5.css");
8
+ const cssDest = path.join(root, "webapp", "css", "exsdk.ui5.css");
9
+
10
+ try {
11
+ if (!fs.existsSync(src)) {
12
+ console.log("[ExSDK] src/controls not found, skipping.");
13
+ process.exit(0);
14
+ }
15
+
16
+ if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
17
+
18
+ let copied = 0;
19
+ fs.readdirSync(src).forEach(file => {
20
+ if (!file.endsWith(".js")) return;
21
+ fs.copyFileSync(path.join(src, file), path.join(dest, file));
22
+ copied++;
23
+ });
24
+
25
+ if (fs.existsSync(css)) {
26
+ if (!fs.existsSync(path.dirname(cssDest))) {
27
+ fs.mkdirSync(path.dirname(cssDest), { recursive: true });
28
+ }
29
+ fs.copyFileSync(css, cssDest);
30
+ console.log("[ExSDK] CSS copied to webapp/css/exsdk.ui5.css");
31
+ }
32
+
33
+ console.log(`[ExSDK] ${copied} control(s) copied to webapp/control/`);
34
+ } catch (e) {
35
+ console.warn("[ExSDK] postinstall warning:", e.message);
36
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "exsdk-ui5",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
- "description": "Modern UI component SDK for SAP Fiori & UI5 — beautiful, fast, framework-independent",
5
+ "description": "Modern UI component SDK for SAP Fiori & UI5",
6
6
  "author": "ExSDK",
7
7
  "license": "SEE LICENSE IN LICENSE.md",
8
8
  "main": "dist/exsdk.ui5.cjs.js",
@@ -19,14 +19,13 @@
19
19
  "files": [
20
20
  "dist",
21
21
  "src/controls",
22
- "ui5-wrapper",
23
- "README.md",
24
- "LICENSE.md"
22
+ "copy-exsdk.cjs",
23
+ "README.md"
25
24
  ],
26
25
  "scripts": {
27
- "build": "rollup -c",
28
- "watch": "rollup -c --watch",
29
- "version": "node scripts/version.js"
26
+ "build": "rollup -c",
27
+ "watch": "rollup -c --watch",
28
+ "postinstall": "node copy-exsdk.cjs"
30
29
  },
31
30
  "devDependencies": {
32
31
  "rollup": "^4.0.0",
@@ -34,12 +33,9 @@
34
33
  "@rollup/plugin-node-resolve": "^15.0.0",
35
34
  "postcss": "^8.4.0"
36
35
  },
37
- "keywords": [
38
- "sap", "ui5", "fiori", "sdk", "components",
39
- "table", "form", "kanban", "button"
40
- ],
36
+ "keywords": ["sap", "ui5", "fiori", "sdk", "components"],
41
37
  "repository": {
42
38
  "type": "git",
43
- "url": "https://github.com/exsdk/ui5"
39
+ "url": "https://github.com/exsdk/ui5.git"
44
40
  }
45
41
  }
@@ -1,210 +1,210 @@
1
- sap.ui.define([
2
- "sap/ui/core/Control"
3
- ], function (Control) {
4
- "use strict";
5
-
6
- return Control.extend("exsdk.controls.ExButton", {
7
-
8
- metadata: {
9
- properties: {
10
- text: { type: "string", defaultValue: "Button" },
11
- // primary | secondary | ghost | danger | pill | gradient | glass | text-btn
12
- type: { type: "string", defaultValue: "primary" },
13
- // sm | md | lg
14
- size: { type: "string", defaultValue: "md" },
15
- icon: { type: "string", defaultValue: "" },
16
- iconPos: { type: "string", defaultValue: "left" }, // left | right
17
- iconOnly: { type: "boolean", defaultValue: false },
18
- loading: { type: "boolean", defaultValue: false },
19
- enabled: { type: "boolean", defaultValue: true },
20
- // success | error | idle
21
- state: { type: "string", defaultValue: "idle" },
22
- width: { type: "string", defaultValue: "" } // "full" veya px değeri
23
- },
24
- events: {
25
- press: {}
26
- }
27
- },
28
-
29
- renderer: function (oRM, oControl) {
30
- oRM.openStart("div", oControl);
31
- oRM.class("ex-btn-wrapper");
32
- oRM.openEnd();
33
- oRM.close("div");
34
- },
35
-
36
- onAfterRendering: function () {
37
- this._render();
38
- },
39
-
40
- // =============================
41
- // RENDER
42
- // =============================
43
- _render: function () {
44
- const oWrapper = this.getDomRef();
45
- if (!oWrapper) return;
46
-
47
- const type = this.getType();
48
- const size = this.getSize();
49
- const text = this.getText();
50
- const icon = this.getIcon();
51
- const iconPos = this.getIconPos();
52
- const iconOnly = this.getIconOnly();
53
- const loading = this.getLoading();
54
- const enabled = this.getEnabled();
55
- const state = this.getState();
56
- const width = this.getWidth();
57
-
58
- const isDisabled = !enabled || loading;
59
-
60
- // State'e göre icon & metin
61
- let displayText = text;
62
- let displayIcon = icon;
63
-
64
- if (state === "success") {
65
- displayText = "Başarılı";
66
- displayIcon = "✓";
67
- } else if (state === "error") {
68
- displayText = "Hata";
69
- displayIcon = "✕";
70
- } else if (loading) {
71
- displayText = "Yükleniyor...";
72
- }
73
-
74
- const spinnerHTML = `
75
- <span class="ex-btn-icon ex-btn-spinner-icon">
76
- <svg viewBox="0 0 20 20" fill="none">
77
- <circle cx="10" cy="10" r="7"
78
- stroke="currentColor"
79
- stroke-width="2.5"
80
- stroke-linecap="round"
81
- stroke-dasharray="38"
82
- stroke-dashoffset="28"/>
83
- </svg>
84
- </span>`;
85
-
86
- const iconHTML = displayIcon
87
- ? `<span class="ex-btn-icon">${displayIcon}</span>`
88
- : "";
89
-
90
- const textHTML = (!iconOnly || loading || state !== "idle")
91
- ? `<span class="ex-btn-text">${displayText}</span>`
92
- : "";
93
-
94
- const leftContent = (iconPos === "left" && !loading) ? iconHTML : "";
95
- const rightContent = (iconPos === "right" && !loading) ? iconHTML : "";
96
- const loaderHTML = loading ? spinnerHTML : "";
97
-
98
- const widthStyle = width === "full"
99
- ? "width:100%;"
100
- : width ? `width:${width};` : "";
101
-
102
- const stateClass = state !== "idle" ? `ex-btn--${state}` : "";
103
-
104
- oWrapper.innerHTML = `
105
- <button
106
- class="ex-btn ex-btn--${type} ex-btn--${size} ${stateClass} ${iconOnly && state === "idle" && !loading ? "ex-btn--icon-only" : ""} ${loading ? "ex-btn--loading" : ""}"
107
- style="${widthStyle}"
108
- ${isDisabled ? "disabled" : ""}
109
- aria-busy="${loading}"
110
- aria-label="${text}">
111
- <span class="ex-btn-ripple-container"></span>
112
- ${loaderHTML}
113
- ${leftContent}
114
- ${textHTML}
115
- ${rightContent}
116
- </button>
117
- `;
118
-
119
- this._attachEvents(oWrapper);
120
- },
121
-
122
- // =============================
123
- // EVENTS
124
- // =============================
125
- _attachEvents: function (oWrapper) {
126
- const btn = oWrapper.querySelector("button");
127
- if (!btn) return;
128
-
129
- btn.addEventListener("click", (e) => {
130
- if (btn.disabled) return;
131
- this._ripple(btn, e);
132
- this.firePress();
133
- });
134
-
135
- btn.addEventListener("keydown", (e) => {
136
- if ((e.key === "Enter" || e.key === " ") && !btn.disabled) {
137
- e.preventDefault();
138
- this._ripple(btn, null);
139
- this.firePress();
140
- }
141
- });
142
- },
143
-
144
- // =============================
145
- // RIPPLE
146
- // =============================
147
- _ripple: function (btn, e) {
148
- const container = btn.querySelector(".ex-btn-ripple-container");
149
- if (!container) return;
150
-
151
- const circle = document.createElement("span");
152
- circle.className = "ex-btn-ripple";
153
-
154
- const rect = btn.getBoundingClientRect();
155
- const size = Math.max(rect.width, rect.height) * 2;
156
- const x = e ? e.clientX - rect.left - size / 2 : rect.width / 2 - size / 2;
157
- const y = e ? e.clientY - rect.top - size / 2 : rect.height / 2 - size / 2;
158
-
159
- circle.style.cssText = `width:${size}px; height:${size}px; left:${x}px; top:${y}px;`;
160
- container.appendChild(circle);
161
- circle.addEventListener("animationend", () => circle.remove());
162
- },
163
-
164
- // =============================
165
- // PUBLIC SETTERS
166
- // =============================
167
- setText: function (s) {
168
- this.setProperty("text", s, true);
169
- const el = this._getEl(".ex-btn-text");
170
- if (el) el.textContent = s;
171
- },
172
-
173
- setLoading: function (b) {
174
- this.setProperty("loading", b, true);
175
- this._render();
176
- },
177
-
178
- setEnabled: function (b) {
179
- this.setProperty("enabled", b, true);
180
- const btn = this._getEl("button");
181
- if (btn) btn.disabled = !b || this.getLoading();
182
- },
183
-
184
- setType: function (s) {
185
- this.setProperty("type", s, true);
186
- this._render();
187
- },
188
-
189
- setState: function (s) {
190
- this.setProperty("state", s, true);
191
- this._render();
192
-
193
- // success / error sonrası otomatik idle'a dön
194
- if (s === "success" || s === "error") {
195
- setTimeout(() => {
196
- this.setProperty("state", "idle", true);
197
- this._render();
198
- }, 2000);
199
- }
200
- },
201
-
202
- // =============================
203
- // UTILS
204
- // =============================
205
- _getEl: function (sel) {
206
- const w = this.getDomRef();
207
- return w ? w.querySelector(sel) : null;
208
- }
209
- });
210
- });
1
+ sap.ui.define([
2
+ "sap/ui/core/Control"
3
+ ], function (Control) {
4
+ "use strict";
5
+
6
+ return Control.extend("project1.control.ExButton", {
7
+
8
+ metadata: {
9
+ properties: {
10
+ text: { type: "string", defaultValue: "Button" },
11
+ // primary | secondary | ghost | danger | pill | gradient | glass | text-btn
12
+ type: { type: "string", defaultValue: "primary" },
13
+ // sm | md | lg
14
+ size: { type: "string", defaultValue: "md" },
15
+ icon: { type: "string", defaultValue: "" },
16
+ iconPos: { type: "string", defaultValue: "left" }, // left | right
17
+ iconOnly: { type: "boolean", defaultValue: false },
18
+ loading: { type: "boolean", defaultValue: false },
19
+ enabled: { type: "boolean", defaultValue: true },
20
+ // success | error | idle
21
+ state: { type: "string", defaultValue: "idle" },
22
+ width: { type: "string", defaultValue: "" } // "full" veya px değeri
23
+ },
24
+ events: {
25
+ press: {}
26
+ }
27
+ },
28
+
29
+ renderer: function (oRM, oControl) {
30
+ oRM.openStart("div", oControl);
31
+ oRM.class("ex-btn-wrapper");
32
+ oRM.openEnd();
33
+ oRM.close("div");
34
+ },
35
+
36
+ onAfterRendering: function () {
37
+ this._render();
38
+ },
39
+
40
+ // =============================
41
+ // RENDER
42
+ // =============================
43
+ _render: function () {
44
+ const oWrapper = this.getDomRef();
45
+ if (!oWrapper) return;
46
+
47
+ const type = this.getType();
48
+ const size = this.getSize();
49
+ const text = this.getText();
50
+ const icon = this.getIcon();
51
+ const iconPos = this.getIconPos();
52
+ const iconOnly = this.getIconOnly();
53
+ const loading = this.getLoading();
54
+ const enabled = this.getEnabled();
55
+ const state = this.getState();
56
+ const width = this.getWidth();
57
+
58
+ const isDisabled = !enabled || loading;
59
+
60
+ // State'e göre icon & metin
61
+ let displayText = text;
62
+ let displayIcon = icon;
63
+
64
+ if (state === "success") {
65
+ displayText = "Başarılı";
66
+ displayIcon = "✓";
67
+ } else if (state === "error") {
68
+ displayText = "Hata";
69
+ displayIcon = "✕";
70
+ } else if (loading) {
71
+ displayText = "Yükleniyor...";
72
+ }
73
+
74
+ const spinnerHTML = `
75
+ <span class="ex-btn-icon ex-btn-spinner-icon">
76
+ <svg viewBox="0 0 20 20" fill="none">
77
+ <circle cx="10" cy="10" r="7"
78
+ stroke="currentColor"
79
+ stroke-width="2.5"
80
+ stroke-linecap="round"
81
+ stroke-dasharray="38"
82
+ stroke-dashoffset="28"/>
83
+ </svg>
84
+ </span>`;
85
+
86
+ const iconHTML = displayIcon
87
+ ? `<span class="ex-btn-icon">${displayIcon}</span>`
88
+ : "";
89
+
90
+ const textHTML = (!iconOnly || loading || state !== "idle")
91
+ ? `<span class="ex-btn-text">${displayText}</span>`
92
+ : "";
93
+
94
+ const leftContent = (iconPos === "left" && !loading) ? iconHTML : "";
95
+ const rightContent = (iconPos === "right" && !loading) ? iconHTML : "";
96
+ const loaderHTML = loading ? spinnerHTML : "";
97
+
98
+ const widthStyle = width === "full"
99
+ ? "width:100%;"
100
+ : width ? `width:${width};` : "";
101
+
102
+ const stateClass = state !== "idle" ? `ex-btn--${state}` : "";
103
+
104
+ oWrapper.innerHTML = `
105
+ <button
106
+ class="ex-btn ex-btn--${type} ex-btn--${size} ${stateClass} ${iconOnly && state === "idle" && !loading ? "ex-btn--icon-only" : ""} ${loading ? "ex-btn--loading" : ""}"
107
+ style="${widthStyle}"
108
+ ${isDisabled ? "disabled" : ""}
109
+ aria-busy="${loading}"
110
+ aria-label="${text}">
111
+ <span class="ex-btn-ripple-container"></span>
112
+ ${loaderHTML}
113
+ ${leftContent}
114
+ ${textHTML}
115
+ ${rightContent}
116
+ </button>
117
+ `;
118
+
119
+ this._attachEvents(oWrapper);
120
+ },
121
+
122
+ // =============================
123
+ // EVENTS
124
+ // =============================
125
+ _attachEvents: function (oWrapper) {
126
+ const btn = oWrapper.querySelector("button");
127
+ if (!btn) return;
128
+
129
+ btn.addEventListener("click", (e) => {
130
+ if (btn.disabled) return;
131
+ this._ripple(btn, e);
132
+ this.firePress();
133
+ });
134
+
135
+ btn.addEventListener("keydown", (e) => {
136
+ if ((e.key === "Enter" || e.key === " ") && !btn.disabled) {
137
+ e.preventDefault();
138
+ this._ripple(btn, null);
139
+ this.firePress();
140
+ }
141
+ });
142
+ },
143
+
144
+ // =============================
145
+ // RIPPLE
146
+ // =============================
147
+ _ripple: function (btn, e) {
148
+ const container = btn.querySelector(".ex-btn-ripple-container");
149
+ if (!container) return;
150
+
151
+ const circle = document.createElement("span");
152
+ circle.className = "ex-btn-ripple";
153
+
154
+ const rect = btn.getBoundingClientRect();
155
+ const size = Math.max(rect.width, rect.height) * 2;
156
+ const x = e ? e.clientX - rect.left - size / 2 : rect.width / 2 - size / 2;
157
+ const y = e ? e.clientY - rect.top - size / 2 : rect.height / 2 - size / 2;
158
+
159
+ circle.style.cssText = `width:${size}px; height:${size}px; left:${x}px; top:${y}px;`;
160
+ container.appendChild(circle);
161
+ circle.addEventListener("animationend", () => circle.remove());
162
+ },
163
+
164
+ // =============================
165
+ // PUBLIC SETTERS
166
+ // =============================
167
+ setText: function (s) {
168
+ this.setProperty("text", s, true);
169
+ const el = this._getEl(".ex-btn-text");
170
+ if (el) el.textContent = s;
171
+ },
172
+
173
+ setLoading: function (b) {
174
+ this.setProperty("loading", b, true);
175
+ this._render();
176
+ },
177
+
178
+ setEnabled: function (b) {
179
+ this.setProperty("enabled", b, true);
180
+ const btn = this._getEl("button");
181
+ if (btn) btn.disabled = !b || this.getLoading();
182
+ },
183
+
184
+ setType: function (s) {
185
+ this.setProperty("type", s, true);
186
+ this._render();
187
+ },
188
+
189
+ setState: function (s) {
190
+ this.setProperty("state", s, true);
191
+ this._render();
192
+
193
+ // success / error sonrası otomatik idle'a dön
194
+ if (s === "success" || s === "error") {
195
+ setTimeout(() => {
196
+ this.setProperty("state", "idle", true);
197
+ this._render();
198
+ }, 2000);
199
+ }
200
+ },
201
+
202
+ // =============================
203
+ // UTILS
204
+ // =============================
205
+ _getEl: function (sel) {
206
+ const w = this.getDomRef();
207
+ return w ? w.querySelector(sel) : null;
208
+ }
209
+ });
210
+ });