exsdk-ui5 0.1.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.
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # @exsdk/ui5
2
+
3
+ Modern UI Component SDK for SAP Fiori & UI5.
4
+
5
+ Beautiful, fast, framework-independent components that work inside any Fiori project — no BTP, no migration needed.
6
+
7
+ ## Quick Start
8
+
9
+ ### CDN (UI5 projeleri için — en kolay yol)
10
+ ```html
11
+ <!-- index.html veya flpSandbox.html içine ekle -->
12
+ <script src="https://cdn.exsdk.io/0.1.0/exsdk.ui5.umd.js"></script>
13
+ <link href="https://cdn.exsdk.io/0.1.0/exsdk.ui5.css" rel="stylesheet">
14
+
15
+ <script>
16
+ ExSDK.ExCore.init({ licenseKey: "YOUR_KEY" });
17
+ </script>
18
+ ```
19
+
20
+ ### npm
21
+ ```bash
22
+ npm install @exsdk/ui5
23
+ ```
24
+
25
+ ```js
26
+ import ExCore, { ExButton, ExTable } from "@exsdk/ui5";
27
+ import "@exsdk/ui5/css";
28
+
29
+ await ExCore.init({ licenseKey: "YOUR_KEY" });
30
+ ```
31
+
32
+ ## UI5 Custom Control olarak kullanım
33
+
34
+ ```xml
35
+ <!-- View XML -->
36
+ <mvc:View
37
+ xmlns:ex="project1.control">
38
+ <ex:ExTable id="myTable" title="Ürünler" columns="{/columns}" rows="{/rows}" />
39
+ <ex:ExButton text="Kaydet" type="primary" press=".onSave" />
40
+ </mvc:View>
41
+ ```
42
+
43
+ ## Components
44
+
45
+ | Component | Tier | Açıklama |
46
+ |----------------|------------|---------------------------------|
47
+ | ExButton | Free | 8 tip, ripple, loading states |
48
+ | ExTable | Free | Virtual scroll, sort, resize |
49
+ | ExForm | Free | 6 field tipi, validation |
50
+ | ExFileUploader | Free | Drag & drop, preview |
51
+ | ExKanban | Pro | Sürükle-bırak lanes |
52
+ | ExChart | Pro | Line, bar, pie, donut |
53
+ | ExTimeline | Pro | Gantt, bağımlılık |
54
+ | ExDashboard | Enterprise | Widget grid |
55
+
56
+ ## Theming
57
+
58
+ ```js
59
+ ExCore.theme.apply({
60
+ "--ex-primary": "#FF5A00", // marka rengin
61
+ "--ex-radius": "4px" // köşe yuvarlaklığı
62
+ });
63
+ ```
64
+
65
+ ## Docs
66
+
67
+ → [exsdk.io/docs](https://exsdk.io/docs)
@@ -0,0 +1,167 @@
1
+ /*!
2
+ * @exsdk/ui5 v0.1.0
3
+ * Modern UI Component SDK for SAP Fiori & UI5
4
+ * (c) 2026 ExSDK
5
+ * Released under commercial license — see LICENSE.md
6
+ */
7
+ 'use strict';
8
+
9
+ const LICENSE_SERVER = "https://license.exsdk.io/v1/verify";
10
+ const LOCAL_KEY = "exsdk_license";
11
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
12
+
13
+ let _tier = "free", _verified = false;
14
+
15
+ const ExLicense = {
16
+ async init(licenseKey) {
17
+ if (!licenseKey) { _tier = "free"; return _tier; }
18
+ const cached = this._getCache(licenseKey);
19
+ if (cached) { _tier = cached.tier; _verified = true; return _tier; }
20
+ try {
21
+ const res = await fetch(LICENSE_SERVER, {
22
+ method: "POST",
23
+ headers: { "Content-Type": "application/json" },
24
+ body: JSON.stringify({ key: licenseKey, domain: window.location.hostname, sdk: "0.1.0" })
25
+ });
26
+ if (!res.ok) throw new Error();
27
+ const data = await res.json();
28
+ _tier = data.tier || "free"; _verified = true;
29
+ this._setCache(licenseKey, _tier);
30
+ } catch {
31
+ console.warn("[ExSDK] License check failed, running in free mode");
32
+ _tier = "free";
33
+ }
34
+ return _tier;
35
+ },
36
+ isRestricted(componentTier) {
37
+ const o = { free: 0, pro: 1, enterprise: 2 };
38
+ return (o[_tier] || 0) < (o[componentTier] || 0);
39
+ },
40
+ getTier() { return _tier; },
41
+ isVerified() { return _verified; },
42
+ isPro() { return _tier === "pro" || _tier === "enterprise"; },
43
+ _getCache(key) {
44
+ try {
45
+ const d = JSON.parse(localStorage.getItem(LOCAL_KEY));
46
+ if (!d || d.key !== key || Date.now() - d.ts > CACHE_TTL_MS) return null;
47
+ return d;
48
+ } catch { return null; }
49
+ },
50
+ _setCache(key, tier) {
51
+ try { localStorage.setItem(LOCAL_KEY, JSON.stringify({ key, tier, ts: Date.now() })); } catch {}
52
+ }
53
+ };
54
+
55
+ /**
56
+ * ExTheme — CSS token yönetimi
57
+ * Müşteri kendi marka renklerini buradan override eder
58
+ */
59
+ const DEFAULTS = {
60
+ "--ex-primary": "#0070f2",
61
+ "--ex-primary-hover": "#005fd4",
62
+ "--ex-danger": "#e54646",
63
+ "--ex-success": "#0f8c3b",
64
+ "--ex-warning": "#e8a000",
65
+ "--ex-text": "#1d2d3e",
66
+ "--ex-text-muted": "#556b82",
67
+ "--ex-border": "#e4e5e7",
68
+ "--ex-radius": "8px",
69
+ "--ex-radius-lg": "12px",
70
+ "--ex-font": '"72", "72full", Arial, sans-serif'
71
+ };
72
+
73
+ const ExTheme = {
74
+ // Varsayılan tema — SDK yüklenince çağırılır
75
+ applyDefault() {
76
+ this.apply(DEFAULTS);
77
+ },
78
+
79
+ // Müşteri override — sadece verilen token'lar güncellenir
80
+ apply(tokens = {}) {
81
+ const root = document.documentElement;
82
+ Object.entries(tokens).forEach(([k, v]) => {
83
+ root.style.setProperty(k, v);
84
+ });
85
+ },
86
+
87
+ // Tek token oku
88
+ get(token) {
89
+ return getComputedStyle(document.documentElement)
90
+ .getPropertyValue(token).trim();
91
+ },
92
+
93
+ // Hazır preset temalar
94
+ presets: {
95
+ horizon: {
96
+ "--ex-primary": "#0070f2",
97
+ "--ex-primary-hover": "#005fd4",
98
+ "--ex-radius": "8px"
99
+ },
100
+ dark: {
101
+ "--ex-text": "#e8eaed",
102
+ "--ex-text-muted": "#9aa0a6",
103
+ "--ex-border": "#3c4043"
104
+ },
105
+ rounded: {
106
+ "--ex-radius": "12px",
107
+ "--ex-radius-lg": "20px"
108
+ }
109
+ }
110
+ };
111
+
112
+ /**
113
+ * ExCore — SDK başlatıcı
114
+ * Kullanım:
115
+ * import ExCore from "@exsdk/ui5"
116
+ * await ExCore.init({ licenseKey: "xxx", theme: "horizon" })
117
+ */
118
+
119
+ const ExCore = {
120
+ async init({ licenseKey, theme } = {}) {
121
+ // 1. Tema uygula
122
+ ExTheme.applyDefault();
123
+ if (theme && ExTheme.presets[theme]) {
124
+ ExTheme.apply(ExTheme.presets[theme]);
125
+ }
126
+
127
+ // 2. Lisans doğrula
128
+ const tier = await ExLicense.init(licenseKey);
129
+
130
+ console.log(`[ExSDK] v0.1.0 initialized — tier: ${tier}`);
131
+ return { tier };
132
+ },
133
+
134
+ get license() { return ExLicense; },
135
+ get theme() { return ExTheme; }
136
+ };
137
+
138
+ /**
139
+ * @exsdk/ui5 — Public API
140
+ *
141
+ * UI5 projesinde kullanım:
142
+ * webapp/control/ klasörüne kopyala, sap.ui.define ile kullan
143
+ *
144
+ * CDN kullanımı:
145
+ * <script src="exsdk.ui5.umd.js"></script>
146
+ * window.ExSDK mevcut olur
147
+ */
148
+
149
+
150
+ const VERSION = "0.1.0";
151
+ const TIER = { FREE: "free", PRO: "pro", ENTERPRISE: "enterprise" };
152
+
153
+ // UI5 Custom Control dosyaları sap.ui.define formatında olduğu için
154
+ // doğrudan Rollup'a girmez — webapp/control/ altına kopyalanır.
155
+ // Aşağıdaki liste hangi dosyaların nereye kopyalanacağını belgeler:
156
+ //
157
+ // ExButton.js → webapp/control/ExButton.js (free)
158
+ // ExTable.js → webapp/control/ExTable.js (free)
159
+ // ExForm.js → webapp/control/ExForm.js (free)
160
+ // ExFileUploader.js → webapp/control/ExFileUploader.js (free)
161
+ // ExKanban.js → webapp/control/ExKanban.js (pro)
162
+
163
+ exports.ExCore = ExCore;
164
+ exports.ExLicense = ExLicense;
165
+ exports.ExTheme = ExTheme;
166
+ exports.TIER = TIER;
167
+ exports.VERSION = VERSION;
@@ -0,0 +1 @@
1
+ .ex-table-wrapper{padding:1rem}.ex-table{background:#fff;border:1px solid #e4e5e7;border-radius:12px;box-shadow:0 1px 4px rgba(0,0,0,.06);font-family:"72","72full",Arial,sans-serif;overflow:hidden}.ex-table-header{align-items:center;background:#fff;border-bottom:1px solid #e4e5e7;display:flex;justify-content:space-between;padding:12px 16px}.ex-table-title{color:#1d2d3e;font-size:14px;font-weight:700}.ex-table-total{background:#f0f4f7;border-radius:20px;color:#556b82;font-size:12px;padding:2px 10px}.ex-table-body{height:400px;overflow:auto;position:relative}.ex-table-body::-webkit-scrollbar{height:6px;width:6px}.ex-table-body::-webkit-scrollbar-track{background:transparent}.ex-table-body::-webkit-scrollbar-thumb{background:#c5cdd6;border-radius:3px}.ex-table-body::-webkit-scrollbar-thumb:hover{background:#8fa3b5}.ex-table-inner{border-collapse:collapse;table-layout:fixed;width:100%}.ex-table-thead th{background:#f5f7f9;border-bottom:2px solid #e4e5e7;overflow:hidden;padding:0;position:sticky;top:0;user-select:none;white-space:nowrap;z-index:2}.ex-th-inner{align-items:center;cursor:pointer;display:flex;gap:4px;padding:10px 14px}.ex-th-label{color:#556b82;flex:1;font-size:12px;font-weight:700;letter-spacing:.4px;text-transform:uppercase}.ex-th-sort{color:#8fa3b5;font-size:11px;transition:color .15s}.ex-table-thead th:hover .ex-th-sort{color:#0070f2}.resize-handle{background:transparent;cursor:col-resize;height:100%;position:absolute;right:0;top:0;transition:background .15s;width:4px}.resize-handle:active,.resize-handle:hover{background:#0070f2}.ex-table-row{border-bottom:1px solid #f0f2f4;transition:background .1s}.ex-table-row:hover{background:#f0f6ff;cursor:pointer}.ex-td{color:#1d2d3e;font-size:14px;overflow:hidden;padding:10px 14px;text-overflow:ellipsis;white-space:nowrap}.ex-td-empty{color:#8fa3b5;font-size:14px;padding:48px 0;text-align:center}.ex-form-wrapper{padding:1rem}.ex-form{background:#fff;border:1px solid #e4e5e7;border-radius:12px;box-shadow:0 1px 4px rgba(0,0,0,.06);font-family:"72","72full",Arial,sans-serif;overflow:hidden}.ex-form-header{border-bottom:1px solid #e4e5e7;padding:14px 20px}.ex-form-title{color:#1d2d3e;font-size:14px;font-weight:700}.ex-form-body{padding:20px}.ex-form-grid{display:grid;gap:16px 24px;grid-template-columns:1fr 1fr}.ex-form-field:has(.ex-form-file-zone),.ex-form-field:has(.ex-form-textarea){grid-column:1/-1}.ex-form-field{display:flex;flex-direction:column;gap:6px}.ex-form-label{color:#556b82;font-size:12px;font-weight:600}.ex-form-required .ex-form-label:after{color:#e54646;content:" *"}.ex-form-input{background:#fff;border:1px solid #c5cdd6;border-radius:8px;box-sizing:border-box;color:#1d2d3e;font-family:inherit;font-size:14px;height:36px;outline:none;padding:0 12px;transition:border-color .15s,box-shadow .15s;width:100%}.ex-form-input:focus{border-color:#0070f2;box-shadow:0 0 0 3px rgba(0,112,242,.12)}.ex-form-textarea{height:90px;padding:10px 12px;resize:vertical}.ex-form-select{appearance:none;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath fill='%23556b82' d='M6 8 1 3h10z'/%3E%3C/svg%3E");background-position:right 12px center;background-repeat:no-repeat;cursor:pointer;padding-right:32px}.ex-form-checkbox-label,.ex-form-radio-label{align-items:center;color:#1d2d3e;cursor:pointer;display:flex;font-size:14px;gap:8px;margin-bottom:6px}.ex-form-checkbox,.ex-form-radio{display:none}.ex-form-checkbox-custom{background:#fff;border:2px solid #c5cdd6;border-radius:4px;flex-shrink:0;height:18px;position:relative;transition:all .15s;width:18px}.ex-form-checkbox:checked+.ex-form-checkbox-custom{background:#0070f2;border-color:#0070f2}.ex-form-checkbox:checked+.ex-form-checkbox-custom:after{border:2px solid #fff;border-left:none;border-top:none;content:"";height:10px;left:4px;position:absolute;top:1px;transform:rotate(45deg);width:6px}.ex-form-radio-custom{background:#fff;border:2px solid #c5cdd6;border-radius:50%;flex-shrink:0;height:18px;position:relative;transition:all .15s;width:18px}.ex-form-radio:checked+.ex-form-radio-custom{border-color:#0070f2}.ex-form-radio:checked+.ex-form-radio-custom:after{background:#0070f2;border-radius:50%;content:"";height:8px;left:3px;position:absolute;top:3px;width:8px}.ex-form-file-zone{border:2px dashed #c5cdd6;border-radius:10px;cursor:pointer;padding:24px;position:relative;text-align:center;transition:border-color .15s,background .15s}.ex-form-file-drag,.ex-form-file-zone:hover{background:#f0f6ff;border-color:#0070f2}.ex-form-file-input{display:none}.ex-form-file-label{align-items:center;color:#556b82;display:flex;flex-direction:column;font-size:14px;gap:6px;pointer-events:none}.ex-form-file-icon{color:#0070f2;font-size:24px}.ex-form-file-name{color:#0070f2;font-size:12px;font-weight:600}.ex-form-error{color:#e54646;font-size:12px;min-height:16px}.ex-form-field-error .ex-form-input,.ex-form-field-error .ex-form-select,.ex-form-field-error .ex-form-textarea{border-color:#e54646;box-shadow:0 0 0 3px rgba(229,70,70,.1)}.ex-form-footer{background:#fafbfc;border-top:1px solid #e4e5e7;display:flex;gap:10px;justify-content:flex-end;padding:14px 20px}.ex-btn{font-family:inherit;font-size:14px;height:36px;padding:0 20px;transition:all .15s}.ex-btn-primary{background:#0070f2;color:#fff}.ex-btn-primary:hover{background:#0058c4}.ex-btn-primary:disabled{background:#8fa3b5;cursor:not-allowed}.ex-btn-ghost{background:transparent;border:1px solid #c5cdd6;color:#556b82}.ex-btn-ghost:hover{background:#f5f7f9}.ex-form-toast{animation:ex-toast-in .2s ease;border-radius:8px;bottom:20px;box-shadow:0 4px 12px rgba(0,0,0,.12);font-size:14px;font-weight:600;padding:12px 20px;position:absolute;right:20px;z-index:100}.ex-form-toast-success{background:#e6f4ea;color:#1a7f37}.ex-form-toast-error{background:#fde8e8;color:#c0392b}@keyframes ex-toast-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.ex-fu-wrapper{padding:1rem}.ex-fu{background:#fff;border:1px solid #e4e5e7;border-radius:12px;box-shadow:0 1px 4px rgba(0,0,0,.06);font-family:"72","72full",Arial,sans-serif;overflow:hidden}.ex-fu-header{align-items:center;border-bottom:1px solid #e4e5e7;display:flex;justify-content:space-between;padding:12px 16px}.ex-fu-title{color:#1d2d3e;font-size:14px;font-weight:700}.ex-fu-meta{color:#8fa3b5;font-size:12px}.ex-fu-zone{border:2px dashed #c5cdd6;border-radius:10px;cursor:pointer;margin:16px;outline:none;transition:border-color .15s,background .15s}.ex-fu-drag,.ex-fu-zone:focus,.ex-fu-zone:hover{background:#f0f6ff;border-color:#0070f2}.ex-fu-zone-inner{align-items:center;display:flex;flex-direction:column;gap:6px;padding:28px 20px;pointer-events:none}.ex-fu-zone-text{color:#1d2d3e;font-size:14px;font-weight:600;margin:0}.ex-fu-zone-sub{color:#8fa3b5;font-size:13px;margin:0}.ex-fu-browse{color:#0070f2;font-weight:600;text-decoration:underline}.ex-fu-input{display:none}.ex-fu-list{display:flex;flex-direction:column;gap:8px;padding:0 16px 16px}.ex-fu-item{align-items:center;background:#fafbfc;border:1px solid #e4e5e7;border-radius:8px;display:flex;gap:12px;padding:10px 12px;transition:border-color .15s}.ex-fu-item-error{background:#fff8f8;border-color:#f5c0c0}.ex-fu-thumb{align-items:center;background:#f0f4f7;border-radius:6px;display:flex;flex-shrink:0;height:44px;justify-content:center;overflow:hidden;width:44px}.ex-fu-preview{height:100%;object-fit:cover;width:100%}.ex-fu-ext{color:#556b82;font-size:11px;font-weight:700;letter-spacing:.5px}.ex-fu-info{display:flex;flex:1;flex-direction:column;gap:4px;min-width:0}.ex-fu-name{color:#1d2d3e;font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ex-fu-size{color:#8fa3b5;font-size:12px}.ex-fu-error-msg{color:#e54646;font-size:12px;font-weight:500}.ex-fu-progress-bar{background:#e4e5e7;border-radius:2px;height:4px;overflow:hidden}.ex-fu-progress-fill{background:#0070f2;border-radius:2px;height:100%;transition:width .3s ease}.ex-fu-remove{background:none;border:none;border-radius:4px;color:#8fa3b5;cursor:pointer;flex-shrink:0;font-size:14px;line-height:1;padding:4px 6px;transition:color .15s,background .15s}.ex-fu-remove:hover{background:#fff0f0;color:#e54646}.ex-kb-wrapper{padding:1rem}.ex-kb{background:#f8f9fb;border:1px solid #e4e5e7;border-radius:12px;box-shadow:0 1px 4px rgba(0,0,0,.06);font-family:"72","72full",Arial,sans-serif;overflow:hidden}.ex-kb-header{align-items:center;background:#fff;border-bottom:1px solid #e4e5e7;display:flex;justify-content:space-between;padding:12px 16px}.ex-kb-title{color:#1d2d3e;font-size:14px;font-weight:700}.ex-kb-board{align-items:flex-start;display:flex;gap:12px;min-height:400px;overflow-x:auto;padding:16px}.ex-kb-board::-webkit-scrollbar{height:6px}.ex-kb-board::-webkit-scrollbar-thumb{background:#c5cdd6;border-radius:3px}.ex-kb-lane{background:#fff;border:1px solid #e4e5e7;border-radius:10px;display:flex;flex-direction:column;flex-shrink:0;max-width:260px;min-width:260px}.ex-kb-lane-header{align-items:center;border-bottom:1px solid #f0f2f4;display:flex;justify-content:space-between;padding:10px 14px}.ex-kb-lane-title{color:#1d2d3e;font-size:13px;font-weight:700}.ex-kb-lane-count{background:#f0f4f7;border-radius:20px;color:#556b82;font-size:11px;font-weight:600;padding:1px 8px}.ex-kb-lane-body{display:flex;flex:1;flex-direction:column;gap:8px;min-height:80px;padding:10px;position:relative;transition:background .15s}.ex-kb-lane-over{background:#f0f6ff;border-radius:0 0 10px 10px}.ex-kb-lane-footer{padding:6px 10px 10px}.ex-kb-drop-indicator{background:transparent;border-radius:2px;height:2px;transition:background .15s}.ex-kb-lane-over .ex-kb-drop-indicator{background:#0070f2}.ex-kb-card{background:#fff;border:1px solid #e4e5e7;border-radius:8px;cursor:grab;padding:10px 12px;transition:box-shadow .15s,opacity .15s;user-select:none}.ex-kb-card:hover{box-shadow:0 2px 8px rgba(0,0,0,.1)}.ex-kb-card-dragging{cursor:grabbing;opacity:.4}.ex-kb-card-top{align-items:flex-start;display:flex;gap:8px;justify-content:space-between}.ex-kb-card-title{color:#1d2d3e;flex:1;font-size:13px;font-weight:600;line-height:1.4}.ex-kb-card-desc{color:#8fa3b5;font-size:12px;line-height:1.5;margin:6px 0 0}.ex-kb-card-bottom{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.ex-kb-priority{border-radius:20px;font-size:11px;font-weight:600;padding:2px 8px}.ex-kb-card-menu{background:none;border:none;border-radius:4px;color:#8fa3b5;cursor:pointer;flex-shrink:0;font-size:16px;line-height:1;padding:0 2px;transition:color .15s,background .15s}.ex-kb-card-menu:hover{background:#f0f2f4;color:#1d2d3e}.ex-kb-card-menu-popup{background:#fff;border:1px solid #e4e5e7;border-radius:8px;box-shadow:0 4px 16px rgba(0,0,0,.12);min-width:160px;overflow:hidden;position:absolute;z-index:50}.ex-kb-menu-item{color:#1d2d3e;cursor:pointer;font-size:13px;padding:10px 16px;transition:background .1s}.ex-kb-menu-item:hover{background:#f5f7f9}.ex-kb-menu-delete:hover{background:#fff0f0;color:#e54646}.ex-kb-btn-ghost{background:none;border:1px dashed #c5cdd6;border-radius:8px;color:#8fa3b5;cursor:pointer;font-family:inherit;font-size:12px;padding:6px 12px;transition:all .15s;width:100%}.ex-kb-btn-ghost:hover{background:#f0f6ff;border-color:#0070f2;color:#0070f2}.ex-kb-btn-primary{background:#0070f2;border:none;border-radius:8px;color:#fff;cursor:pointer;font-family:inherit;font-size:13px;font-weight:600;padding:8px 20px;transition:background .15s}.ex-kb-btn-primary:hover{background:#0058c4}.ex-kb-popup{align-items:center;background:rgba(0,0,0,.35);border-radius:12px;display:flex;inset:0;justify-content:center;position:absolute;z-index:100}.ex-kb-popup-box{background:#fff;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,.18);max-width:440px;overflow:hidden;width:100%}.ex-kb-popup-header{align-items:center;border-bottom:1px solid #e4e5e7;color:#1d2d3e;display:flex;font-size:14px;font-weight:700;justify-content:space-between;padding:14px 20px}.ex-kb-popup-close{background:none;border:none;border-radius:4px;color:#8fa3b5;cursor:pointer;font-size:16px;padding:2px 6px}.ex-kb-popup-close:hover{background:#f0f2f4;color:#1d2d3e}.ex-kb-popup-body{display:flex;flex-direction:column;gap:8px;padding:16px 20px}.ex-kb-popup-label{color:#556b82;font-size:12px;font-weight:600;margin-top:4px}.ex-kb-popup-input{border:1px solid #c5cdd6;border-radius:8px;box-sizing:border-box;color:#1d2d3e;font-family:inherit;font-size:14px;height:36px;outline:none;padding:0 12px;transition:border-color .15s;width:100%}.ex-kb-popup-input:focus{border-color:#0070f2}.ex-kb-popup-textarea{height:70px;padding:8px 12px;resize:none}.ex-kb-popup-footer{background:#fafbfc;border-top:1px solid #e4e5e7;display:flex;gap:10px;justify-content:flex-end;padding:12px 20px}.ex-kb-color-picker{display:flex;flex-wrap:wrap;gap:8px}.ex-kb-color-dot{border:2px solid transparent;border-radius:50%;cursor:pointer;height:24px;transition:transform .1s,border-color .1s;width:24px}.ex-kb-color-dot:hover{transform:scale(1.15)}.ex-kb-color-selected{border-color:#1d2d3e!important;transform:scale(1.15)}.ex-kb-detail-badge{background:#f0f4f7;border-radius:20px;color:#556b82;display:inline-block;font-size:12px;font-weight:600;padding:3px 10px}.ex-btn{transition:background .15s ease,color .15s ease,border-color .15s ease,box-shadow .15s ease,transform .1s ease}.ex-btn:not(:disabled):active{transform:scale(.97)}.ex-btn:focus-visible{box-shadow:0 0 0 3px rgba(0,112,242,.3)}.ex-btn--lg{height:44px;padding:0 24px}.ex-btn--icon-only.ex-btn--lg{width:44px}.ex-btn--primary:not(:disabled):hover{background:#0060d0;box-shadow:0 4px 12px rgba(0,112,242,.35)}.ex-btn--secondary{border:1px solid #c5cdd6}.ex-btn--ghost{border:1px solid #0070f2}.ex-btn--ghost:not(:disabled):hover{background:#f0f6ff}.ex-btn--danger:not(:disabled):hover{box-shadow:0 4px 12px rgba(229,70,70,.35)}.ex-btn--danger:focus-visible{box-shadow:0 0 0 3px rgba(229,70,70,.3)}.ex-btn:disabled{opacity:.45}.ex-btn--lg .ex-btn-icon{font-size:17px}.ex-btn-spinner{align-items:center;display:inline-flex;flex-shrink:0;justify-content:center}.ex-btn-spinner svg{animation:ex-spin .7s linear infinite;height:15px;width:15px}.ex-btn--sm .ex-btn-spinner svg{height:13px;width:13px}.ex-btn--lg .ex-btn-spinner svg{height:17px;width:17px}.ex-btn-ripple{animation:ex-ripple .5s ease-out forwards;background:hsla(0,0%,100%,.35)}.ex-btn--ghost .ex-btn-ripple,.ex-btn--secondary .ex-btn-ripple{background:rgba(0,112,242,.15)}.ex-btn-wrapper{display:inline-block}.ex-btn{align-items:center;border:none;border-radius:8px;cursor:pointer;display:inline-flex;font-family:"72","72full",Arial,sans-serif;font-weight:600;gap:7px;justify-content:center;letter-spacing:.01em;outline:none;overflow:hidden;position:relative;transition:background .15s ease,color .15s ease,border-color .15s ease,box-shadow .18s ease,transform .1s ease;user-select:none;white-space:nowrap}.ex-btn:not(:disabled):active{transform:scale(.96)}.ex-btn:focus-visible{box-shadow:0 0 0 3px rgba(0,112,242,.28);outline:none}.ex-btn--sm{border-radius:6px;font-size:12px;gap:5px;height:28px;padding:0 12px}.ex-btn--md{font-size:14px;height:36px;padding:0 18px}.ex-btn--lg{border-radius:10px;font-size:15px;gap:9px;height:46px;padding:0 26px}.ex-btn--icon-only.ex-btn--sm{padding:0;width:28px}.ex-btn--icon-only.ex-btn--md{padding:0;width:36px}.ex-btn--icon-only.ex-btn--lg{padding:0;width:46px}.ex-btn--primary{background:#0070f2;box-shadow:0 1px 2px rgba(0,112,242,.2);color:#fff}.ex-btn--primary:not(:disabled):hover{background:#005fd4;box-shadow:0 4px 14px rgba(0,112,242,.38)}.ex-btn--secondary{background:#f0f4f7;border:1.5px solid #d0d8e0;color:#1d2d3e}.ex-btn--secondary:not(:disabled):hover{background:#e4eaf0;border-color:#8fa3b5;box-shadow:0 2px 8px rgba(0,0,0,.08)}.ex-btn--secondary:focus-visible{box-shadow:0 0 0 3px rgba(100,130,160,.25)}.ex-btn--ghost{background:transparent;border:1.5px solid #0070f2;color:#0070f2}.ex-btn--ghost:not(:disabled):hover{background:#eef5ff;box-shadow:0 2px 8px rgba(0,112,242,.15)}.ex-btn--ghost .ex-btn-ripple{background:rgba(0,112,242,.12)}.ex-btn--danger{background:#e54646;box-shadow:0 1px 2px rgba(229,70,70,.2);color:#fff}.ex-btn--danger:not(:disabled):hover{background:#c73030;box-shadow:0 4px 14px rgba(229,70,70,.38)}.ex-btn--danger:focus-visible{box-shadow:0 0 0 3px rgba(229,70,70,.28)}.ex-btn--pill{background:#0070f2;border-radius:100px;box-shadow:0 1px 2px rgba(0,112,242,.2);color:#fff}.ex-btn--pill:not(:disabled):hover{background:#005fd4;box-shadow:0 4px 14px rgba(0,112,242,.38)}.ex-btn--gradient{background:linear-gradient(135deg,#0070f2,#7c3aed);background-size:200% 200%;border:none;box-shadow:0 2px 8px rgba(124,58,237,.25);color:#fff;transition:box-shadow .18s,transform .1s,background-position .3s}.ex-btn--gradient:not(:disabled):hover{background-position:100%;box-shadow:0 4px 18px rgba(124,58,237,.42)}.ex-btn--gradient:focus-visible{box-shadow:0 0 0 3px rgba(124,58,237,.3)}.ex-btn--gradient .ex-btn-ripple{background:hsla(0,0%,100%,.25)}.ex-btn--glass{backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);background:hsla(0,0%,100%,.18);border:1.5px solid hsla(0,0%,100%,.45);box-shadow:0 2px 12px rgba(0,0,0,.08);color:#1d2d3e}.ex-btn--glass:not(:disabled):hover{background:hsla(0,0%,100%,.3);box-shadow:0 4px 20px rgba(0,0,0,.14)}.ex-btn--glass .ex-btn-ripple{background:hsla(0,0%,100%,.35)}.ex-btn--text-btn{background:transparent;border:none;border-radius:4px;box-shadow:none;color:#0070f2;padding-left:4px;padding-right:4px}.ex-btn--text-btn:not(:disabled):hover{background:#eef5ff;text-decoration:underline}.ex-btn--text-btn .ex-btn-ripple{background:rgba(0,112,242,.1)}.ex-btn:disabled{box-shadow:none!important;cursor:not-allowed;opacity:.42;pointer-events:none;transform:none!important}.ex-btn--loading{cursor:wait;pointer-events:none}.ex-btn--success{background:#0f8c3b!important;box-shadow:0 2px 8px rgba(15,140,59,.3)!important;color:#fff!important}.ex-btn--error{background:#e54646!important;box-shadow:0 2px 8px rgba(229,70,70,.3)!important;color:#fff!important}.ex-btn-icon{align-items:center;display:inline-flex;flex-shrink:0;font-size:15px;justify-content:center;line-height:1}.ex-btn--sm .ex-btn-icon{font-size:13px}.ex-btn--lg .ex-btn-icon{font-size:18px}.ex-btn-spinner-icon svg{animation:ex-spin .65s linear infinite;height:15px;width:15px}.ex-btn--sm .ex-btn-spinner-icon svg{height:13px;width:13px}.ex-btn--lg .ex-btn-spinner-icon svg{height:17px;width:17px}@keyframes ex-spin{to{transform:rotate(1turn)}}.ex-btn-ripple-container{border-radius:inherit;inset:0;overflow:hidden;pointer-events:none;position:absolute}.ex-btn-ripple{animation:ex-ripple .55s ease-out forwards;background:hsla(0,0%,100%,.3);border-radius:50%;pointer-events:none;position:absolute;transform:scale(0)}.ex-btn--secondary .ex-btn-ripple{background:rgba(0,112,242,.1)}@keyframes ex-ripple{to{opacity:0;transform:scale(1)}}.ex-btn-text{pointer-events:none;position:relative;z-index:1}
@@ -0,0 +1,161 @@
1
+ /*!
2
+ * @exsdk/ui5 v0.1.0
3
+ * Modern UI Component SDK for SAP Fiori & UI5
4
+ * (c) 2026 ExSDK
5
+ * Released under commercial license — see LICENSE.md
6
+ */
7
+ const LICENSE_SERVER = "https://license.exsdk.io/v1/verify";
8
+ const LOCAL_KEY = "exsdk_license";
9
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
10
+
11
+ let _tier = "free", _verified = false;
12
+
13
+ const ExLicense = {
14
+ async init(licenseKey) {
15
+ if (!licenseKey) { _tier = "free"; return _tier; }
16
+ const cached = this._getCache(licenseKey);
17
+ if (cached) { _tier = cached.tier; _verified = true; return _tier; }
18
+ try {
19
+ const res = await fetch(LICENSE_SERVER, {
20
+ method: "POST",
21
+ headers: { "Content-Type": "application/json" },
22
+ body: JSON.stringify({ key: licenseKey, domain: window.location.hostname, sdk: "0.1.0" })
23
+ });
24
+ if (!res.ok) throw new Error();
25
+ const data = await res.json();
26
+ _tier = data.tier || "free"; _verified = true;
27
+ this._setCache(licenseKey, _tier);
28
+ } catch {
29
+ console.warn("[ExSDK] License check failed, running in free mode");
30
+ _tier = "free";
31
+ }
32
+ return _tier;
33
+ },
34
+ isRestricted(componentTier) {
35
+ const o = { free: 0, pro: 1, enterprise: 2 };
36
+ return (o[_tier] || 0) < (o[componentTier] || 0);
37
+ },
38
+ getTier() { return _tier; },
39
+ isVerified() { return _verified; },
40
+ isPro() { return _tier === "pro" || _tier === "enterprise"; },
41
+ _getCache(key) {
42
+ try {
43
+ const d = JSON.parse(localStorage.getItem(LOCAL_KEY));
44
+ if (!d || d.key !== key || Date.now() - d.ts > CACHE_TTL_MS) return null;
45
+ return d;
46
+ } catch { return null; }
47
+ },
48
+ _setCache(key, tier) {
49
+ try { localStorage.setItem(LOCAL_KEY, JSON.stringify({ key, tier, ts: Date.now() })); } catch {}
50
+ }
51
+ };
52
+
53
+ /**
54
+ * ExTheme — CSS token yönetimi
55
+ * Müşteri kendi marka renklerini buradan override eder
56
+ */
57
+ const DEFAULTS = {
58
+ "--ex-primary": "#0070f2",
59
+ "--ex-primary-hover": "#005fd4",
60
+ "--ex-danger": "#e54646",
61
+ "--ex-success": "#0f8c3b",
62
+ "--ex-warning": "#e8a000",
63
+ "--ex-text": "#1d2d3e",
64
+ "--ex-text-muted": "#556b82",
65
+ "--ex-border": "#e4e5e7",
66
+ "--ex-radius": "8px",
67
+ "--ex-radius-lg": "12px",
68
+ "--ex-font": '"72", "72full", Arial, sans-serif'
69
+ };
70
+
71
+ const ExTheme = {
72
+ // Varsayılan tema — SDK yüklenince çağırılır
73
+ applyDefault() {
74
+ this.apply(DEFAULTS);
75
+ },
76
+
77
+ // Müşteri override — sadece verilen token'lar güncellenir
78
+ apply(tokens = {}) {
79
+ const root = document.documentElement;
80
+ Object.entries(tokens).forEach(([k, v]) => {
81
+ root.style.setProperty(k, v);
82
+ });
83
+ },
84
+
85
+ // Tek token oku
86
+ get(token) {
87
+ return getComputedStyle(document.documentElement)
88
+ .getPropertyValue(token).trim();
89
+ },
90
+
91
+ // Hazır preset temalar
92
+ presets: {
93
+ horizon: {
94
+ "--ex-primary": "#0070f2",
95
+ "--ex-primary-hover": "#005fd4",
96
+ "--ex-radius": "8px"
97
+ },
98
+ dark: {
99
+ "--ex-text": "#e8eaed",
100
+ "--ex-text-muted": "#9aa0a6",
101
+ "--ex-border": "#3c4043"
102
+ },
103
+ rounded: {
104
+ "--ex-radius": "12px",
105
+ "--ex-radius-lg": "20px"
106
+ }
107
+ }
108
+ };
109
+
110
+ /**
111
+ * ExCore — SDK başlatıcı
112
+ * Kullanım:
113
+ * import ExCore from "@exsdk/ui5"
114
+ * await ExCore.init({ licenseKey: "xxx", theme: "horizon" })
115
+ */
116
+
117
+ const ExCore = {
118
+ async init({ licenseKey, theme } = {}) {
119
+ // 1. Tema uygula
120
+ ExTheme.applyDefault();
121
+ if (theme && ExTheme.presets[theme]) {
122
+ ExTheme.apply(ExTheme.presets[theme]);
123
+ }
124
+
125
+ // 2. Lisans doğrula
126
+ const tier = await ExLicense.init(licenseKey);
127
+
128
+ console.log(`[ExSDK] v0.1.0 initialized — tier: ${tier}`);
129
+ return { tier };
130
+ },
131
+
132
+ get license() { return ExLicense; },
133
+ get theme() { return ExTheme; }
134
+ };
135
+
136
+ /**
137
+ * @exsdk/ui5 — Public API
138
+ *
139
+ * UI5 projesinde kullanım:
140
+ * webapp/control/ klasörüne kopyala, sap.ui.define ile kullan
141
+ *
142
+ * CDN kullanımı:
143
+ * <script src="exsdk.ui5.umd.js"></script>
144
+ * window.ExSDK mevcut olur
145
+ */
146
+
147
+
148
+ const VERSION = "0.1.0";
149
+ const TIER = { FREE: "free", PRO: "pro", ENTERPRISE: "enterprise" };
150
+
151
+ // UI5 Custom Control dosyaları sap.ui.define formatında olduğu için
152
+ // doğrudan Rollup'a girmez — webapp/control/ altına kopyalanır.
153
+ // Aşağıdaki liste hangi dosyaların nereye kopyalanacağını belgeler:
154
+ //
155
+ // ExButton.js → webapp/control/ExButton.js (free)
156
+ // ExTable.js → webapp/control/ExTable.js (free)
157
+ // ExForm.js → webapp/control/ExForm.js (free)
158
+ // ExFileUploader.js → webapp/control/ExFileUploader.js (free)
159
+ // ExKanban.js → webapp/control/ExKanban.js (pro)
160
+
161
+ export { ExCore, ExLicense, ExTheme, TIER, VERSION };
@@ -0,0 +1,173 @@
1
+ /*!
2
+ * @exsdk/ui5 v0.1.0
3
+ * Modern UI Component SDK for SAP Fiori & UI5
4
+ * (c) 2026 ExSDK
5
+ * Released under commercial license — see LICENSE.md
6
+ */
7
+ (function (global, factory) {
8
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
9
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
10
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ExSDK = {}));
11
+ })(this, (function (exports) { 'use strict';
12
+
13
+ const LICENSE_SERVER = "https://license.exsdk.io/v1/verify";
14
+ const LOCAL_KEY = "exsdk_license";
15
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
16
+
17
+ let _tier = "free", _verified = false;
18
+
19
+ const ExLicense = {
20
+ async init(licenseKey) {
21
+ if (!licenseKey) { _tier = "free"; return _tier; }
22
+ const cached = this._getCache(licenseKey);
23
+ if (cached) { _tier = cached.tier; _verified = true; return _tier; }
24
+ try {
25
+ const res = await fetch(LICENSE_SERVER, {
26
+ method: "POST",
27
+ headers: { "Content-Type": "application/json" },
28
+ body: JSON.stringify({ key: licenseKey, domain: window.location.hostname, sdk: "0.1.0" })
29
+ });
30
+ if (!res.ok) throw new Error();
31
+ const data = await res.json();
32
+ _tier = data.tier || "free"; _verified = true;
33
+ this._setCache(licenseKey, _tier);
34
+ } catch {
35
+ console.warn("[ExSDK] License check failed, running in free mode");
36
+ _tier = "free";
37
+ }
38
+ return _tier;
39
+ },
40
+ isRestricted(componentTier) {
41
+ const o = { free: 0, pro: 1, enterprise: 2 };
42
+ return (o[_tier] || 0) < (o[componentTier] || 0);
43
+ },
44
+ getTier() { return _tier; },
45
+ isVerified() { return _verified; },
46
+ isPro() { return _tier === "pro" || _tier === "enterprise"; },
47
+ _getCache(key) {
48
+ try {
49
+ const d = JSON.parse(localStorage.getItem(LOCAL_KEY));
50
+ if (!d || d.key !== key || Date.now() - d.ts > CACHE_TTL_MS) return null;
51
+ return d;
52
+ } catch { return null; }
53
+ },
54
+ _setCache(key, tier) {
55
+ try { localStorage.setItem(LOCAL_KEY, JSON.stringify({ key, tier, ts: Date.now() })); } catch {}
56
+ }
57
+ };
58
+
59
+ /**
60
+ * ExTheme — CSS token yönetimi
61
+ * Müşteri kendi marka renklerini buradan override eder
62
+ */
63
+ const DEFAULTS = {
64
+ "--ex-primary": "#0070f2",
65
+ "--ex-primary-hover": "#005fd4",
66
+ "--ex-danger": "#e54646",
67
+ "--ex-success": "#0f8c3b",
68
+ "--ex-warning": "#e8a000",
69
+ "--ex-text": "#1d2d3e",
70
+ "--ex-text-muted": "#556b82",
71
+ "--ex-border": "#e4e5e7",
72
+ "--ex-radius": "8px",
73
+ "--ex-radius-lg": "12px",
74
+ "--ex-font": '"72", "72full", Arial, sans-serif'
75
+ };
76
+
77
+ const ExTheme = {
78
+ // Varsayılan tema — SDK yüklenince çağırılır
79
+ applyDefault() {
80
+ this.apply(DEFAULTS);
81
+ },
82
+
83
+ // Müşteri override — sadece verilen token'lar güncellenir
84
+ apply(tokens = {}) {
85
+ const root = document.documentElement;
86
+ Object.entries(tokens).forEach(([k, v]) => {
87
+ root.style.setProperty(k, v);
88
+ });
89
+ },
90
+
91
+ // Tek token oku
92
+ get(token) {
93
+ return getComputedStyle(document.documentElement)
94
+ .getPropertyValue(token).trim();
95
+ },
96
+
97
+ // Hazır preset temalar
98
+ presets: {
99
+ horizon: {
100
+ "--ex-primary": "#0070f2",
101
+ "--ex-primary-hover": "#005fd4",
102
+ "--ex-radius": "8px"
103
+ },
104
+ dark: {
105
+ "--ex-text": "#e8eaed",
106
+ "--ex-text-muted": "#9aa0a6",
107
+ "--ex-border": "#3c4043"
108
+ },
109
+ rounded: {
110
+ "--ex-radius": "12px",
111
+ "--ex-radius-lg": "20px"
112
+ }
113
+ }
114
+ };
115
+
116
+ /**
117
+ * ExCore — SDK başlatıcı
118
+ * Kullanım:
119
+ * import ExCore from "@exsdk/ui5"
120
+ * await ExCore.init({ licenseKey: "xxx", theme: "horizon" })
121
+ */
122
+
123
+ const ExCore = {
124
+ async init({ licenseKey, theme } = {}) {
125
+ // 1. Tema uygula
126
+ ExTheme.applyDefault();
127
+ if (theme && ExTheme.presets[theme]) {
128
+ ExTheme.apply(ExTheme.presets[theme]);
129
+ }
130
+
131
+ // 2. Lisans doğrula
132
+ const tier = await ExLicense.init(licenseKey);
133
+
134
+ console.log(`[ExSDK] v0.1.0 initialized — tier: ${tier}`);
135
+ return { tier };
136
+ },
137
+
138
+ get license() { return ExLicense; },
139
+ get theme() { return ExTheme; }
140
+ };
141
+
142
+ /**
143
+ * @exsdk/ui5 — Public API
144
+ *
145
+ * UI5 projesinde kullanım:
146
+ * webapp/control/ klasörüne kopyala, sap.ui.define ile kullan
147
+ *
148
+ * CDN kullanımı:
149
+ * <script src="exsdk.ui5.umd.js"></script>
150
+ * window.ExSDK mevcut olur
151
+ */
152
+
153
+
154
+ const VERSION = "0.1.0";
155
+ const TIER = { FREE: "free", PRO: "pro", ENTERPRISE: "enterprise" };
156
+
157
+ // UI5 Custom Control dosyaları sap.ui.define formatında olduğu için
158
+ // doğrudan Rollup'a girmez — webapp/control/ altına kopyalanır.
159
+ // Aşağıdaki liste hangi dosyaların nereye kopyalanacağını belgeler:
160
+ //
161
+ // ExButton.js → webapp/control/ExButton.js (free)
162
+ // ExTable.js → webapp/control/ExTable.js (free)
163
+ // ExForm.js → webapp/control/ExForm.js (free)
164
+ // ExFileUploader.js → webapp/control/ExFileUploader.js (free)
165
+ // ExKanban.js → webapp/control/ExKanban.js (pro)
166
+
167
+ exports.ExCore = ExCore;
168
+ exports.ExLicense = ExLicense;
169
+ exports.ExTheme = ExTheme;
170
+ exports.TIER = TIER;
171
+ exports.VERSION = VERSION;
172
+
173
+ }));
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "exsdk-ui5",
3
+ "version": "0.1.0",
4
+ "description": "Modern UI component SDK for SAP Fiori & UI5 — beautiful, fast, framework-independent",
5
+ "author": "ExSDK",
6
+ "license": "SEE LICENSE IN LICENSE.md",
7
+ "main": "dist/exsdk.ui5.cjs.js",
8
+ "module": "dist/exsdk.ui5.esm.js",
9
+ "browser": "dist/exsdk.ui5.umd.js",
10
+ "style": "dist/exsdk.ui5.css",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/exsdk.ui5.esm.js",
14
+ "require": "./dist/exsdk.ui5.cjs.js"
15
+ },
16
+ "./css": "./dist/exsdk.ui5.css"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "ui5-wrapper",
21
+ "README.md",
22
+ "LICENSE.md"
23
+ ],
24
+ "scripts": {
25
+ "build": "rollup -c",
26
+ "watch": "rollup -c --watch",
27
+ "version": "node scripts/version.js"
28
+ },
29
+ "devDependencies": {
30
+ "rollup": "^4.0.0",
31
+ "rollup-plugin-postcss": "^4.0.2",
32
+ "@rollup/plugin-node-resolve": "^15.0.0",
33
+ "postcss": "^8.4.0"
34
+ },
35
+ "keywords": [
36
+ "sap", "ui5", "fiori", "sdk", "components",
37
+ "table", "form", "kanban", "button"
38
+ ],
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/exsdk/ui5"
42
+ }
43
+ }