@onetype/framework 2.0.49 → 2.0.52

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 (104) hide show
  1. package/addons/core/commands/front/directives/run.js +1 -1
  2. package/addons/core/commands/front/directives/submit.js +1 -1
  3. package/addons/core/commands/front/functions/api.js +1 -1
  4. package/addons/core/database/back/addon.js +14 -0
  5. package/addons/core/database/back/events/addon.init.js +42 -0
  6. package/addons/core/database/back/events/addon.item.init.js +24 -0
  7. package/addons/core/database/back/functions/item/create.js +92 -0
  8. package/addons/core/database/back/functions/item/delete.js +34 -0
  9. package/addons/core/database/back/functions/item/save.js +13 -0
  10. package/addons/core/database/back/functions/item/update.js +90 -0
  11. package/addons/core/database/back/functions/items/builder.js +160 -0
  12. package/addons/core/database/back/functions/items/filter.js +32 -0
  13. package/addons/core/database/back/functions/items/filters.js +7 -0
  14. package/addons/core/database/back/functions/items/find.js +28 -0
  15. package/addons/core/database/back/functions/items/methods/aggregate.js +15 -0
  16. package/addons/core/database/back/functions/items/methods/count.js +12 -0
  17. package/addons/core/database/back/functions/items/methods/exists.js +8 -0
  18. package/addons/core/database/back/functions/items/methods/many.js +13 -0
  19. package/addons/core/database/back/functions/items/methods/one.js +8 -0
  20. package/addons/core/database/back/functions/items/methods/plain.js +29 -0
  21. package/addons/core/database/back/functions/items/methods/query.js +33 -0
  22. package/addons/core/database/back/functions/items/methods.js +142 -0
  23. package/addons/core/database/back/functions/items/transform/join.js +63 -0
  24. package/addons/core/database/back/functions/items/transform/translate.js +57 -0
  25. package/addons/core/database/back/functions/items/validation.js +125 -0
  26. package/addons/core/database/back/item/catch/add.js +1 -1
  27. package/addons/core/database/back/items/commands/create.js +54 -0
  28. package/addons/core/database/back/items/commands/delete.js +62 -0
  29. package/addons/core/database/back/items/commands/find.js +118 -0
  30. package/addons/core/database/back/items/commands/update.js +70 -0
  31. package/addons/core/database/back/load.js +27 -26
  32. package/addons/core/database/front/events/addon.init.js +42 -0
  33. package/addons/core/database/front/functions/create.js +11 -0
  34. package/addons/core/database/front/functions/delete.js +10 -0
  35. package/addons/core/database/front/functions/find.js +96 -142
  36. package/addons/core/database/front/functions/update.js +12 -0
  37. package/addons/float/popup/css/popup.css +141 -18
  38. package/addons/float/popup/js/addon.js +5 -0
  39. package/addons/float/popup/js/functions/confirm.js +100 -0
  40. package/addons/float/popup/js/functions/toast.js +1 -1
  41. package/addons/float/popup/js/items/directives/tooltip.js +5 -1
  42. package/addons/render/directives/front/addon.js +5 -0
  43. package/addons/render/directives/front/functions/process/data.js +19 -1
  44. package/addons/render/directives/front/functions/process/locale.js +46 -0
  45. package/addons/render/directives/front/functions/process.js +4 -1
  46. package/addons/render/directives/front/items/self/660-form.js +74 -163
  47. package/addons/render/directives/front/items/self/750-html.js +1 -1
  48. package/addons/render/elements/front/items/self/form/button/button.css +9 -0
  49. package/addons/render/elements/front/items/self/form/button/button.js +1 -1
  50. package/addons/render/elements/front/items/self/form/color/color.css +1 -1
  51. package/addons/render/elements/front/items/self/form/color/color.js +25 -10
  52. package/addons/render/elements/front/items/self/form/editor-markdown/editor-markdown.css +410 -0
  53. package/addons/render/elements/front/items/self/form/editor-markdown/editor-markdown.js +191 -0
  54. package/addons/render/elements/front/items/self/form/field/field.css +18 -4
  55. package/addons/render/elements/front/items/self/form/field/field.js +6 -1
  56. package/addons/render/elements/front/items/self/form/section/section.js +3 -1
  57. package/addons/render/elements/front/items/self/navigation/tabs/tabs.css +8 -3
  58. package/addons/render/pages/core/addon.js +1 -1
  59. package/addons/render/pages/front/items/directives/change.js +1 -1
  60. package/addons/render/pages/front/styles/page.css +0 -7
  61. package/addons/render/transforms/js/functions/data.js +21 -2
  62. package/lib/src/classes/addon/class.js +0 -16
  63. package/lib/src/classes/addon/classes/item/class.js +0 -2
  64. package/lib/src/classes/addon/classes/item/mixins/get.js +0 -1
  65. package/lib/src/classes/addon/classes/render/mixins/compile.js +3 -2
  66. package/lib/src/classes/addon/mixins/items.js +2 -0
  67. package/lib/src/mixins/addons.js +2 -0
  68. package/lib/src/mixins/data.js +10 -9
  69. package/lib/src/mixins/emitter.js +5 -1
  70. package/lib/src/mixins/form.js +4 -0
  71. package/lib/src/mixins/function.js +6 -1
  72. package/lib/src/mixins/language.js +55 -0
  73. package/lib/src/mixins/locale.js +49 -0
  74. package/lib/src/onetype.js +6 -11
  75. package/package.json +1 -1
  76. package/addons/core/database/back/events/addon.add.js +0 -18
  77. package/addons/core/database/back/events/middleware/addon.items.find.js +0 -24
  78. package/addons/core/database/back/events/middleware/item.crud.create.js +0 -24
  79. package/addons/core/database/back/events/middleware/item.crud.delete.js +0 -24
  80. package/addons/core/database/back/events/middleware/item.crud.update.js +0 -24
  81. package/addons/core/database/back/functions/create.js +0 -6
  82. package/addons/core/database/back/functions/delete.js +0 -6
  83. package/addons/core/database/back/functions/find/builder.js +0 -160
  84. package/addons/core/database/back/functions/find/count.js +0 -12
  85. package/addons/core/database/back/functions/find/filter.js +0 -37
  86. package/addons/core/database/back/functions/find/filters.js +0 -7
  87. package/addons/core/database/back/functions/find/many.js +0 -93
  88. package/addons/core/database/back/functions/find/methods.js +0 -235
  89. package/addons/core/database/back/functions/find/plain.js +0 -25
  90. package/addons/core/database/back/functions/find/validation.js +0 -214
  91. package/addons/core/database/back/functions/find.js +0 -25
  92. package/addons/core/database/back/functions/update.js +0 -6
  93. package/addons/core/database/back/item/functions/create.js +0 -94
  94. package/addons/core/database/back/item/functions/delete.js +0 -25
  95. package/addons/core/database/back/item/functions/find.js +0 -19
  96. package/addons/core/database/back/item/functions/save.js +0 -15
  97. package/addons/core/database/back/item/functions/transaction.js +0 -17
  98. package/addons/core/database/back/item/functions/update.js +0 -76
  99. package/addons/core/database/back/items/commands/expose.js +0 -321
  100. package/addons/core/database/front/events/addon.add.js +0 -13
  101. package/lib/src/classes/addon/classes/item/mixins/crud.js +0 -28
  102. package/lib/src/classes/addon/mixins/find.js +0 -12
  103. package/lib/src/classes/addon/mixins/table.js +0 -35
  104. package/lib/src/mixins/dependencies.js +0 -104
@@ -0,0 +1,70 @@
1
+ import onetype from '#framework/load.js';
2
+
3
+ onetype.AddonReady('commands', (commands) =>
4
+ {
5
+ commands.Item({
6
+ id: 'database:update',
7
+ exposed: true,
8
+ method: 'POST',
9
+ endpoint: '/api/database/update',
10
+ in: {
11
+ addon: ['string', null, true],
12
+ id: ['string', null, true],
13
+ data: ['object', null, true],
14
+ translation: ['string']
15
+ },
16
+ out: {
17
+ item: ['object']
18
+ },
19
+ callback: async function(properties, resolve)
20
+ {
21
+ const addon = onetype.AddonGet(properties.addon);
22
+
23
+ if(!addon)
24
+ {
25
+ return resolve(null, 'Addon not found.', 404);
26
+ }
27
+
28
+ const expose = addon.database?.expose;
29
+
30
+ if(!expose)
31
+ {
32
+ return resolve(null, 'Addon is not exposed.', 403);
33
+ }
34
+
35
+ if(!expose.update)
36
+ {
37
+ return resolve(null, 'Update is not allowed.', 403);
38
+ }
39
+
40
+ if(!properties.data?.id || (typeof properties.data.id !== 'string' && typeof properties.data.id !== 'number'))
41
+ {
42
+ return resolve(null, 'Invalid or missing id.', 400);
43
+ }
44
+
45
+ const item = await addon.Find({translation: properties.translation}).filter('id', properties.data.id).one(true);
46
+
47
+ if(!item)
48
+ {
49
+ return resolve(null, 'Item not found.', 404);
50
+ }
51
+
52
+ Object.entries(properties.data).forEach(([key, value]) =>
53
+ {
54
+ item.Set(key, value);
55
+ });
56
+
57
+ const allowed = expose.update.call({http: this.http, properties, item});
58
+
59
+ if(allowed !== true)
60
+ {
61
+ return resolve(null, typeof allowed === 'string' ? allowed : 'Update not allowed.', 400);
62
+ }
63
+
64
+ await item.Update({translation: properties.translation});
65
+ const fields = expose.select || Object.keys(addon.Fields().data);
66
+
67
+ resolve({item: item.Get(fields)});
68
+ }
69
+ });
70
+ });
@@ -1,37 +1,38 @@
1
1
  import onetype from '#framework/load.js';
2
- import database from '#database/addon.js';
3
2
 
4
- import '#database/functions/find.js';
5
- import '#database/functions/create.js';
6
- import '#database/functions/update.js';
7
- import '#database/functions/delete.js';
3
+ import '#database/events/addon.init.js';
4
+ import '#database/events/addon.item.init.js';
8
5
 
9
- import '#database/functions/find/many.js';
10
- import '#database/functions/find/count.js';
11
- import '#database/functions/find/plain.js';
12
- import '#database/functions/find/filter.js';
13
- import '#database/functions/find/filters.js';
14
- import '#database/functions/find/methods.js';
15
- import '#database/functions/find/builder.js';
16
- import '#database/functions/find/validation.js';
6
+ import database from '#database/addon.js';
17
7
 
18
- import '#database/item/functions/create.js';
19
- import '#database/item/functions/update.js';
20
- import '#database/item/functions/delete.js';
21
- import '#database/item/functions/find.js';
22
- import '#database/item/functions/save.js';
23
- import '#database/item/functions/transaction.js';
8
+ import '#database/functions/items/find.js';
9
+ import '#database/functions/item/create.js';
10
+ import '#database/functions/item/update.js';
11
+ import '#database/functions/item/delete.js';
12
+ import '#database/functions/item/save.js';
24
13
 
25
- import '#database/item/catch/add.js';
14
+ import '#database/functions/items/filter.js';
15
+ import '#database/functions/items/filters.js';
16
+ import '#database/functions/items/methods.js';
17
+ import '#database/functions/items/builder.js';
18
+ import '#database/functions/items/validation.js';
26
19
 
27
- import '#database/events/addon.add.js';
20
+ import '#database/functions/items/methods/query.js';
21
+ import '#database/functions/items/transform/join.js';
22
+ import '#database/functions/items/transform/translate.js';
23
+ import '#database/functions/items/methods/many.js';
24
+ import '#database/functions/items/methods/one.js';
25
+ import '#database/functions/items/methods/count.js';
26
+ import '#database/functions/items/methods/plain.js';
27
+ import '#database/functions/items/methods/exists.js';
28
+ import '#database/functions/items/methods/aggregate.js';
28
29
 
29
- import '#database/events/middleware/addon.items.find.js';
30
- import '#database/events/middleware/item.crud.create.js';
31
- import '#database/events/middleware/item.crud.update.js';
32
- import '#database/events/middleware/item.crud.delete.js';
30
+ import '#database/item/catch/add.js';
33
31
 
34
- import '#database/items/commands/expose.js';
32
+ import '#database/items/commands/find.js';
33
+ import '#database/items/commands/create.js';
34
+ import '#database/items/commands/update.js';
35
+ import '#database/items/commands/delete.js';
35
36
 
36
37
  onetype.DataSchema('filter', {
37
38
  field: ['string', null, true],
@@ -0,0 +1,42 @@
1
+ onetype.EmitOn('@addon.init', (addon) =>
2
+ {
3
+ addon.database =
4
+ {
5
+ expose: null,
6
+ table: null,
7
+ translations: null
8
+ };
9
+
10
+ addon.Table = function() {};
11
+ addon.Expose = function() {};
12
+ addon.Translations = function() {};
13
+
14
+ addon.Find = function({translation = null} = {})
15
+ {
16
+ translation = translation ? translation : onetype.Language();
17
+
18
+ return database.Fn('find', addon, translation);
19
+ };
20
+ });
21
+
22
+ onetype.EmitOn('@addon.item.init', (item) =>
23
+ {
24
+ item.Create = async function({translation = null} = {})
25
+ {
26
+ translation = translation || onetype.Language();
27
+
28
+ return database.Fn('create', item, translation);
29
+ };
30
+
31
+ item.Update = async function({translation = null} = {})
32
+ {
33
+ translation = translation || onetype.Language();
34
+
35
+ return database.Fn('update', item, translation);
36
+ };
37
+
38
+ item.Delete = async function()
39
+ {
40
+ return database.Fn('delete', item);
41
+ };
42
+ });
@@ -0,0 +1,11 @@
1
+ database.Fn('create', async function(item, translation)
2
+ {
3
+ const result = await $ot.command('database:create', {
4
+ addon: item.addon.name,
5
+ data: item.data,
6
+ translation
7
+ }, true);
8
+
9
+ item.SetData(result.data.item, false);
10
+ return item;
11
+ });
@@ -0,0 +1,10 @@
1
+ database.Fn('delete', async function(item)
2
+ {
3
+ const result = await $ot.command('database:delete', {
4
+ addon: item.addon.name,
5
+ id: item.Get('id')
6
+ }, true);
7
+
8
+ item.Set('id', null);
9
+ return item;
10
+ });
@@ -1,142 +1,96 @@
1
- database.Fn('find', function(addon)
2
- {
3
- const state = {
4
- addon: addon.GetName(),
5
- filters: [],
6
- joins: [],
7
- sort_field: null,
8
- sort_direction: 'asc',
9
- page: 1,
10
- limit: 50
11
- };
12
-
13
- const methods = {};
14
-
15
- methods.filter = function(field, value, operator = 'EQUALS')
16
- {
17
- state.filters.push({ field, value, operator });
18
- return methods;
19
- };
20
-
21
- methods.join = function(addon, field, output, select)
22
- {
23
- const join = { addon, field, output: output || field };
24
-
25
- if(select)
26
- {
27
- join.select = Array.isArray(select) ? select : [select];
28
- }
29
-
30
- state.joins.push(join);
31
- return methods;
32
- };
33
-
34
- methods.sort = function(field, direction = 'asc')
35
- {
36
- state.sort_field = field;
37
- state.sort_direction = direction;
38
- return methods;
39
- };
40
-
41
- methods.page = function(page)
42
- {
43
- state.page = page;
44
- return methods;
45
- };
46
-
47
- methods.limit = function(limit)
48
- {
49
- state.limit = limit;
50
- return methods;
51
- };
52
-
53
- methods.select = function(fields)
54
- {
55
- state.select = Array.isArray(fields) ? fields : [fields];
56
- return methods;
57
- };
58
-
59
- methods.many = async function(set = false)
60
- {
61
- const response = await fetch('/api/database', {
62
- method: 'POST',
63
- headers: {
64
- 'Content-Type': 'application/json'
65
- },
66
- body: JSON.stringify(state)
67
- });
68
-
69
- const result = await response.json();
70
-
71
- if(result.code !== 200)
72
- {
73
- throw new Error(result.message);
74
- }
75
-
76
- const items = result.data.items.map(function(data)
77
- {
78
- return addon.ItemAdd(data, null, false, set);
79
- });
80
-
81
- return items;
82
- };
83
-
84
- methods.one = async function(set = false)
85
- {
86
- state.limit = 1;
87
-
88
- const items = await methods.many(set);
89
-
90
- return items.length > 0 ? items[0] : null;
91
- };
92
-
93
- methods.plain = async function()
94
- {
95
- const response = await fetch('/api/database', {
96
- method: 'POST',
97
- headers: {
98
- 'Content-Type': 'application/json'
99
- },
100
- body: JSON.stringify(state)
101
- });
102
-
103
- const result = await response.json();
104
-
105
- if(result.code !== 200)
106
- {
107
- throw new Error(result.message);
108
- }
109
-
110
- const total = result.data.total || 0;
111
-
112
- return {
113
- items: result.data.items,
114
- total,
115
- page: result.data.page || state.page,
116
- pages: state.limit > 0 ? Math.ceil(total / state.limit) : 1,
117
- limit: result.data.limit || state.limit
118
- };
119
- };
120
-
121
- methods.count = async function()
122
- {
123
- const response = await fetch('/api/database', {
124
- method: 'POST',
125
- headers: {
126
- 'Content-Type': 'application/json'
127
- },
128
- body: JSON.stringify(state)
129
- });
130
-
131
- const result = await response.json();
132
-
133
- if(result.code !== 200)
134
- {
135
- throw new Error(result.message);
136
- }
137
-
138
- return result.data.total;
139
- };
140
-
141
- return methods;
142
- });
1
+ database.Fn('find', function(addon, translation)
2
+ {
3
+ const state = {
4
+ addon: addon.name,
5
+ filters: [],
6
+ sort_field: null,
7
+ sort_direction: 'asc',
8
+ page: 1,
9
+ limit: 50,
10
+ translation
11
+ };
12
+
13
+ const request = async function()
14
+ {
15
+ const response = await fetch('/api/database/find', {
16
+ method: 'POST',
17
+ headers: { 'Content-Type': 'application/json' },
18
+ body: JSON.stringify(state)
19
+ });
20
+
21
+ const result = await response.json();
22
+
23
+ if(result.code !== 200)
24
+ {
25
+ throw new Error(result.message);
26
+ }
27
+
28
+ return result.data;
29
+ };
30
+
31
+ const methods = {};
32
+
33
+ methods.filter = function(field, value, operator = 'EQUALS')
34
+ {
35
+ state.filters.push({ field, value, operator });
36
+ return methods;
37
+ };
38
+
39
+ methods.sort = function(field, direction = 'asc')
40
+ {
41
+ state.sort_field = field;
42
+ state.sort_direction = direction;
43
+ return methods;
44
+ };
45
+
46
+ methods.page = function(page)
47
+ {
48
+ state.page = page;
49
+ return methods;
50
+ };
51
+
52
+ methods.limit = function(limit)
53
+ {
54
+ state.limit = limit;
55
+ return methods;
56
+ };
57
+
58
+ methods.select = function(fields)
59
+ {
60
+ state.select = Array.isArray(fields) ? fields : [fields];
61
+ return methods;
62
+ };
63
+
64
+ methods.many = async function(set = false)
65
+ {
66
+ const data = await request();
67
+ return data.items.map(item => addon.ItemAdd(item, null, false, set));
68
+ };
69
+
70
+ methods.one = async function(set = false)
71
+ {
72
+ state.limit = 1;
73
+ const items = await methods.many(set);
74
+ return items.length > 0 ? items[0] : null;
75
+ };
76
+
77
+ methods.plain = async function()
78
+ {
79
+ return request();
80
+ };
81
+
82
+ methods.count = async function()
83
+ {
84
+ const data = await request();
85
+ return data.total;
86
+ };
87
+
88
+ methods.exists = async function()
89
+ {
90
+ state.limit = 1;
91
+ const data = await request();
92
+ return data.total > 0;
93
+ };
94
+
95
+ return methods;
96
+ });
@@ -0,0 +1,12 @@
1
+ database.Fn('update', async function(item, translation)
2
+ {
3
+ const result = await $ot.command('database:update', {
4
+ addon: item.addon.name,
5
+ id: item.Get('id'),
6
+ data: item.data,
7
+ translation
8
+ }, true);
9
+
10
+ item.SetData(result.data.item, false);
11
+ return item;
12
+ });
@@ -38,23 +38,35 @@
38
38
  .ot-toast
39
39
  {
40
40
  display: flex;
41
- align-items: flex-start;
41
+ align-items: center;
42
42
  gap: var(--ot-spacing-m);
43
- padding: var(--ot-spacing-m);
44
- background: var(--ot-bg-2);
45
- border: 1px solid var(--ot-bg-2-border);
46
- border-radius: var(--ot-radius-m);
43
+ padding: 16px 20px;
44
+ background: var(--ot-bg-1);
45
+ border: 1px solid var(--ot-bg-1-border);
46
+ border-radius: var(--ot-radius-l);
47
47
  color: var(--ot-text-1);
48
48
  font-size: var(--ot-size-m);
49
- min-width: 280px;
50
- max-width: 400px;
51
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
49
+ min-width: 320px;
50
+ max-width: 420px;
51
+ animation: toast-in 0.35s cubic-bezier(0.22, 1, 0.36, 1);
52
+ }
53
+
54
+ @keyframes toast-in
55
+ {
56
+ from { opacity: 0; transform: translateY(-12px) scale(0.96); }
57
+ to { opacity: 1; transform: translateY(0) scale(1); }
52
58
  }
53
59
 
54
60
  .ot-toast > .icon
55
61
  {
56
- font-size: 20px;
57
- margin-top: 1px;
62
+ width: 32px;
63
+ height: 32px;
64
+ border-radius: 8px;
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ font-size: 18px;
69
+ flex-shrink: 0;
58
70
  }
59
71
 
60
72
  .ot-toast > .content
@@ -65,29 +77,140 @@
65
77
  .ot-toast > .content > .title
66
78
  {
67
79
  font-weight: 600;
68
- margin-bottom: 2px;
80
+ font-size: 13.5px;
81
+ margin-bottom: 3px;
82
+ color: var(--ot-text-1);
69
83
  }
70
84
 
71
85
  .ot-toast > .content > .message
72
86
  {
73
- color: var(--ot-text-2);
87
+ font-size: var(--ot-size-m);
88
+ font-weight: 600;
89
+ line-height: 1.45;
90
+ color: var(--ot-text-1);
74
91
  }
75
92
 
76
93
  .ot-toast > .close
77
94
  {
95
+ width: 28px;
96
+ height: 28px;
78
97
  background: none;
79
98
  border: none;
80
- color: var(--ot-text-2);
99
+ color: var(--ot-text-3);
81
100
  cursor: pointer;
82
- padding: 0;
101
+ border-radius: 6px;
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ flex-shrink: 0;
106
+ transition: background 0.15s ease, color 0.15s ease;
83
107
  }
84
108
 
85
109
  .ot-toast > .close:hover
86
110
  {
111
+ background: var(--ot-bg-2);
87
112
  color: var(--ot-text-1);
88
113
  }
89
114
 
90
- .ot-toast.info > .icon { color: var(--ot-blue); }
91
- .ot-toast.success > .icon { color: var(--ot-green); }
92
- .ot-toast.warning > .icon { color: var(--ot-orange); }
93
- .ot-toast.error > .icon { color: var(--ot-red); }
115
+ .ot-toast > .close > i
116
+ {
117
+ font-size: 16px;
118
+ }
119
+
120
+ .ot-toast.info > .icon { background: var(--ot-blue-opacity); color: var(--ot-blue); }
121
+ .ot-toast.success > .icon { background: var(--ot-green-opacity); color: var(--ot-green); }
122
+ .ot-toast.warning > .icon { background: var(--ot-orange-opacity); color: var(--ot-orange); }
123
+ .ot-toast.error > .icon { background: var(--ot-red-opacity); color: var(--ot-red); }
124
+
125
+ /* Confirm */
126
+
127
+ .ot-confirm
128
+ {
129
+ display: flex;
130
+ flex-direction: column;
131
+ padding: 28px 32px 24px;
132
+ background: var(--ot-bg-1);
133
+ border: 1px solid var(--ot-bg-1-border);
134
+ border-radius: 20px;
135
+ min-width: 400px;
136
+ max-width: 460px;
137
+ animation: confirm-in 0.25s cubic-bezier(0.22, 1, 0.36, 1);
138
+ }
139
+
140
+ @keyframes confirm-in
141
+ {
142
+ from { opacity: 0; transform: scale(0.95) translateY(8px); }
143
+ to { opacity: 1; transform: scale(1) translateY(0); }
144
+ }
145
+
146
+ /* Icon */
147
+
148
+ .ot-confirm > .icon
149
+ {
150
+ width: 44px;
151
+ height: 44px;
152
+ border-radius: 12px;
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: center;
156
+ margin-bottom: 18px;
157
+ }
158
+
159
+ .ot-confirm > .icon > i
160
+ {
161
+ font-size: 22px;
162
+ }
163
+
164
+ .ot-confirm > .icon.default { background: var(--ot-brand-opacity); color: var(--ot-brand); }
165
+ .ot-confirm > .icon.danger { background: var(--ot-red-opacity); color: var(--ot-red); }
166
+ .ot-confirm > .icon.warning { background: var(--ot-orange-opacity); color: var(--ot-orange); }
167
+ .ot-confirm > .icon.info { background: var(--ot-blue-opacity); color: var(--ot-blue); }
168
+ .ot-confirm > .icon.success { background: var(--ot-green-opacity); color: var(--ot-green); }
169
+
170
+ /* Title */
171
+
172
+ .ot-confirm > .title
173
+ {
174
+ font-family: var(--ot-font-secondary);
175
+ font-size: 22px;
176
+ font-weight: 500;
177
+ letter-spacing: -0.015em;
178
+ line-height: 1.15;
179
+ color: var(--ot-text-1);
180
+ margin-bottom: 8px;
181
+ }
182
+
183
+ /* Description */
184
+
185
+ .ot-confirm > .description
186
+ {
187
+ font-size: 13.5px;
188
+ line-height: 1.55;
189
+ color: var(--ot-text-2);
190
+ margin-bottom: 24px;
191
+ }
192
+
193
+ /* Input */
194
+
195
+ .ot-confirm > .input
196
+ {
197
+ width: 100%;
198
+ margin-bottom: 24px;
199
+ }
200
+
201
+ /* Actions */
202
+
203
+ .ot-confirm > .actions
204
+ {
205
+ display: flex;
206
+ gap: 10px;
207
+ width: 100%;
208
+ padding-top: 20px;
209
+ border-top: 1px solid var(--ot-bg-1-border);
210
+ }
211
+
212
+ .ot-confirm > .actions > *
213
+ {
214
+ flex: 1;
215
+ width: 100%;
216
+ }
@@ -32,3 +32,8 @@ onetype.$ot.toast = function(message, options)
32
32
  onetype.$ot.toast.open = onetype.$ot.toast;
33
33
  onetype.$ot.toast.close = (id) => popup.Fn('close', id);
34
34
 
35
+ onetype.$ot.confirm = function(title, description, options)
36
+ {
37
+ return popup.Fn('confirm', title, description, options);
38
+ };
39
+