@xuda.io/runtime-bundle 1.0.1422 → 1.0.1423

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.
@@ -1988,6 +1988,13 @@ func.runtime.session.create_state = function (SESSION_ID, options) {
1988
1988
  func.runtime.workers.ensure_registry(SESSION_ID);
1989
1989
  return SESSION_OBJ[SESSION_ID];
1990
1990
  };
1991
+ func.runtime.session.is_slim = function (SESSION_ID) {
1992
+ const session = typeof SESSION_ID === 'undefined' || SESSION_ID === null ? null : SESSION_OBJ?.[SESSION_ID];
1993
+ if (session && typeof session.SLIM_BUNDLE !== 'undefined') {
1994
+ return !!session.SLIM_BUNDLE;
1995
+ }
1996
+ return !!glb.SLIM_BUNDLE;
1997
+ };
1991
1998
  func.runtime.session.set_default_value = function (_session, key, value) {
1992
1999
  _session[key] = value || func.runtime.env.get_default_session_value(key);
1993
2000
  return _session[key];
@@ -2239,6 +2246,135 @@ func.runtime.bind.build_datasource_changes = function (dsSessionP, currentRecord
2239
2246
  },
2240
2247
  };
2241
2248
  };
2249
+ func.runtime.bind.get_native_adapter = function () {
2250
+ const has_explicit_value = function (elm) {
2251
+ return !!elm?.hasAttribute?.('value');
2252
+ };
2253
+ const get_listener_event = function (elm) {
2254
+ const tag_name = elm?.tagName?.toLowerCase?.();
2255
+ const type = (elm?.type || '').toLowerCase();
2256
+
2257
+ if (tag_name === 'select' || ['checkbox', 'radio'].includes(type)) {
2258
+ return 'change';
2259
+ }
2260
+ return 'input';
2261
+ };
2262
+
2263
+ return {
2264
+ getter: function (elm) {
2265
+ if (!elm) {
2266
+ return undefined;
2267
+ }
2268
+
2269
+ const tag_name = elm?.tagName?.toLowerCase?.();
2270
+ const type = (elm?.type || '').toLowerCase();
2271
+
2272
+ if (tag_name === 'select' && elm.multiple) {
2273
+ return Array.from(elm.options || [])
2274
+ .filter(function (option) {
2275
+ return option.selected;
2276
+ })
2277
+ .map(function (option) {
2278
+ return option.value;
2279
+ });
2280
+ }
2281
+
2282
+ if (type === 'checkbox') {
2283
+ return has_explicit_value(elm) ? elm.value : !!elm.checked;
2284
+ }
2285
+
2286
+ if (type === 'radio') {
2287
+ return elm.value;
2288
+ }
2289
+
2290
+ return typeof elm.value !== 'undefined' ? elm.value : undefined;
2291
+ },
2292
+ setter: function (elm, value) {
2293
+ if (!elm) {
2294
+ return false;
2295
+ }
2296
+
2297
+ const tag_name = elm?.tagName?.toLowerCase?.();
2298
+ const type = (elm?.type || '').toLowerCase();
2299
+
2300
+ if (tag_name === 'select' && elm.multiple) {
2301
+ const selected_values = Array.isArray(value)
2302
+ ? value.map(function (item) {
2303
+ return String(item);
2304
+ })
2305
+ : [String(value)];
2306
+ Array.from(elm.options || []).forEach(function (option) {
2307
+ option.selected = selected_values.includes(String(option.value));
2308
+ });
2309
+ return true;
2310
+ }
2311
+
2312
+ if (type === 'checkbox' || type === 'radio') {
2313
+ return true;
2314
+ }
2315
+
2316
+ if (typeof elm.value !== 'undefined') {
2317
+ elm.value = value === null || typeof value === 'undefined' ? '' : String(value);
2318
+ }
2319
+ return true;
2320
+ },
2321
+ listener: function (elm, handler) {
2322
+ if (!elm?.addEventListener || typeof handler !== 'function') {
2323
+ return false;
2324
+ }
2325
+
2326
+ const event_name = get_listener_event(elm);
2327
+ const listener_key = '__xuda_native_bind_listener_' + event_name;
2328
+ if (elm[listener_key]) {
2329
+ elm.removeEventListener(event_name, elm[listener_key]);
2330
+ }
2331
+ elm.addEventListener(event_name, handler);
2332
+ elm[listener_key] = handler;
2333
+ return true;
2334
+ },
2335
+ };
2336
+ };
2337
+ func.runtime.bind.is_valid_adapter = function (adapter) {
2338
+ return !!(
2339
+ adapter &&
2340
+ typeof adapter.getter === 'function' &&
2341
+ typeof adapter.setter === 'function' &&
2342
+ typeof adapter.listener === 'function'
2343
+ );
2344
+ };
2345
+ func.runtime.bind.get_adapter = function (SESSION_ID) {
2346
+ const native_adapter = func.runtime.bind.get_native_adapter();
2347
+ if (func.runtime.session.is_slim(SESSION_ID)) {
2348
+ return native_adapter;
2349
+ }
2350
+
2351
+ const plugin_bind = UI_FRAMEWORK_PLUGIN?.bind;
2352
+ if (!plugin_bind) {
2353
+ return native_adapter;
2354
+ }
2355
+
2356
+ if (func.runtime.bind.is_valid_adapter(plugin_bind)) {
2357
+ return plugin_bind;
2358
+ }
2359
+
2360
+ if (typeof plugin_bind === 'function') {
2361
+ try {
2362
+ const bind_instance = new plugin_bind();
2363
+ if (func.runtime.bind.is_valid_adapter(bind_instance)) {
2364
+ return bind_instance;
2365
+ }
2366
+ } catch (error) {}
2367
+
2368
+ try {
2369
+ const bind_factory = plugin_bind();
2370
+ if (func.runtime.bind.is_valid_adapter(bind_factory)) {
2371
+ return bind_factory;
2372
+ }
2373
+ } catch (error) {}
2374
+ }
2375
+
2376
+ return native_adapter;
2377
+ };
2242
2378
  func.runtime.bind.resolve_field = async function (SESSION_ID, prog_id, dsSessionP, field_id, iterate_info) {
2243
2379
  let _prog_id = prog_id;
2244
2380
  let _dsP = dsSessionP;
@@ -8908,7 +9044,10 @@ func.runtime.ui.find_in_root = function (SESSION_ID, selector) {
8908
9044
  };
8909
9045
  func.runtime.ui.get_root_tag_name = function () {
8910
9046
  let root_tag_name = 'div';
8911
- if (typeof glb.SLIM_BUNDLE === 'undefined' && !glb.SLIM_BUNDLE) {
9047
+ if (!func.runtime.session.is_slim()) {
9048
+ if (typeof UI_FRAMEWORK_PLUGIN?.core !== 'function') {
9049
+ return root_tag_name;
9050
+ }
8912
9051
  const ui_plugin_core = new UI_FRAMEWORK_PLUGIN.core();
8913
9052
  root_tag_name = ui_plugin_core?.rootTagName() || root_tag_name;
8914
9053
  }
@@ -12735,6 +12874,12 @@ func.runtime.ui.close_modal_session = async function (SESSION_ID, modal_id) {
12735
12874
  func.runtime.ui.render_screen_type = async function (options) {
12736
12875
  const $div_content = func.runtime.ui.get_children(options.$div);
12737
12876
  func.runtime.ui.sync_child_parent_container(options.$div);
12877
+ const assert_framework_screen_supported = function (screen_type) {
12878
+ if (!func.runtime.session.is_slim(options.SESSION_ID)) {
12879
+ return;
12880
+ }
12881
+ throw new Error('Slim mode does not support "' + screen_type + '" screens without a UI framework plugin');
12882
+ };
12738
12883
 
12739
12884
  let $ret = options.$div;
12740
12885
  let $nav = func.runtime.ui.get_nav(options.SESSION_ID);
@@ -12742,6 +12887,7 @@ func.runtime.ui.render_screen_type = async function (options) {
12742
12887
 
12743
12888
  switch (options.paramsP.screen_type) {
12744
12889
  case 'modal': {
12890
+ assert_framework_screen_supported('modal');
12745
12891
  params = func.runtime.ui.build_modal_params(options.paramsP, options.$div, options.$container, options.close_modal);
12746
12892
  const modal_id = params.modal_id;
12747
12893
  func.runtime.ui.set_modal_params(options.SESSION_ID, modal_id, params);
@@ -12758,6 +12904,7 @@ func.runtime.ui.render_screen_type = async function (options) {
12758
12904
  }
12759
12905
 
12760
12906
  case 'popover': {
12907
+ assert_framework_screen_supported('popover');
12761
12908
  const xu_popover_controller = func.UI.component.create_app_popover_component(options.SESSION_ID);
12762
12909
  params = func.runtime.ui.build_popover_params(options.paramsP, options.$div, options.$container);
12763
12910
 
@@ -12772,6 +12919,7 @@ func.runtime.ui.render_screen_type = async function (options) {
12772
12919
  }
12773
12920
 
12774
12921
  case 'page': {
12922
+ assert_framework_screen_supported('page');
12775
12923
  const nav = func.runtime.ui.get_first_node($nav);
12776
12924
 
12777
12925
  params = func.runtime.ui.build_page_params(options.SESSION_ID, options.paramsP, $div_content, options.$container, nav);
@@ -17375,7 +17523,7 @@ func.runtime.render.handle_xu_bind = async function (options) {
17375
17523
  return {};
17376
17524
  }
17377
17525
 
17378
- const bind = new UI_FRAMEWORK_PLUGIN.bind();
17526
+ const bind = func.runtime.bind.get_adapter(options.SESSION_ID);
17379
17527
  const field_changed = async function () {
17380
17528
  const _ds = SESSION_OBJ[options.SESSION_ID].DS_GLB[_dsP];
17381
17529
  const field_type = func.runtime.bind.get_field_type(field_prop);
@@ -22433,13 +22581,22 @@ func.index.call_worker = async function (SESSION_ID, obj, params, promiseP) {
22433
22581
  };
22434
22582
 
22435
22583
  func.index.init_SCREEN_BLOCKER = async function (SESSION_ID) {
22584
+ const get_loader = async function () {
22585
+ if (func.runtime.session.is_slim(SESSION_ID) || typeof UI_FRAMEWORK_PLUGIN?.loader !== 'function') {
22586
+ return {
22587
+ dismiss: function () {},
22588
+ };
22589
+ }
22590
+ return await UI_FRAMEWORK_PLUGIN.loader(LOADER_TEXT);
22591
+ };
22592
+
22436
22593
  setInterval(async function () {
22437
22594
  if (glb.CURRENT_APP_LOADING || (!LOADER_ACTIVE && xu_isEmpty(SCREEN_BLOCKER_OBJ))) {
22438
22595
  return;
22439
22596
  }
22440
22597
  glb.CURRENT_APP_LOADING = 1;
22441
22598
 
22442
- const loader = await UI_FRAMEWORK_PLUGIN.loader(LOADER_TEXT);
22599
+ const loader = await get_loader();
22443
22600
 
22444
22601
  glb.CURRENT_APP_LOADING = loader;
22445
22602
 
@@ -1914,6 +1914,13 @@ func.runtime.session.create_state = function (SESSION_ID, options) {
1914
1914
  func.runtime.workers.ensure_registry(SESSION_ID);
1915
1915
  return SESSION_OBJ[SESSION_ID];
1916
1916
  };
1917
+ func.runtime.session.is_slim = function (SESSION_ID) {
1918
+ const session = typeof SESSION_ID === 'undefined' || SESSION_ID === null ? null : SESSION_OBJ?.[SESSION_ID];
1919
+ if (session && typeof session.SLIM_BUNDLE !== 'undefined') {
1920
+ return !!session.SLIM_BUNDLE;
1921
+ }
1922
+ return !!glb.SLIM_BUNDLE;
1923
+ };
1917
1924
  func.runtime.session.set_default_value = function (_session, key, value) {
1918
1925
  _session[key] = value || func.runtime.env.get_default_session_value(key);
1919
1926
  return _session[key];
@@ -2165,6 +2172,135 @@ func.runtime.bind.build_datasource_changes = function (dsSessionP, currentRecord
2165
2172
  },
2166
2173
  };
2167
2174
  };
2175
+ func.runtime.bind.get_native_adapter = function () {
2176
+ const has_explicit_value = function (elm) {
2177
+ return !!elm?.hasAttribute?.('value');
2178
+ };
2179
+ const get_listener_event = function (elm) {
2180
+ const tag_name = elm?.tagName?.toLowerCase?.();
2181
+ const type = (elm?.type || '').toLowerCase();
2182
+
2183
+ if (tag_name === 'select' || ['checkbox', 'radio'].includes(type)) {
2184
+ return 'change';
2185
+ }
2186
+ return 'input';
2187
+ };
2188
+
2189
+ return {
2190
+ getter: function (elm) {
2191
+ if (!elm) {
2192
+ return undefined;
2193
+ }
2194
+
2195
+ const tag_name = elm?.tagName?.toLowerCase?.();
2196
+ const type = (elm?.type || '').toLowerCase();
2197
+
2198
+ if (tag_name === 'select' && elm.multiple) {
2199
+ return Array.from(elm.options || [])
2200
+ .filter(function (option) {
2201
+ return option.selected;
2202
+ })
2203
+ .map(function (option) {
2204
+ return option.value;
2205
+ });
2206
+ }
2207
+
2208
+ if (type === 'checkbox') {
2209
+ return has_explicit_value(elm) ? elm.value : !!elm.checked;
2210
+ }
2211
+
2212
+ if (type === 'radio') {
2213
+ return elm.value;
2214
+ }
2215
+
2216
+ return typeof elm.value !== 'undefined' ? elm.value : undefined;
2217
+ },
2218
+ setter: function (elm, value) {
2219
+ if (!elm) {
2220
+ return false;
2221
+ }
2222
+
2223
+ const tag_name = elm?.tagName?.toLowerCase?.();
2224
+ const type = (elm?.type || '').toLowerCase();
2225
+
2226
+ if (tag_name === 'select' && elm.multiple) {
2227
+ const selected_values = Array.isArray(value)
2228
+ ? value.map(function (item) {
2229
+ return String(item);
2230
+ })
2231
+ : [String(value)];
2232
+ Array.from(elm.options || []).forEach(function (option) {
2233
+ option.selected = selected_values.includes(String(option.value));
2234
+ });
2235
+ return true;
2236
+ }
2237
+
2238
+ if (type === 'checkbox' || type === 'radio') {
2239
+ return true;
2240
+ }
2241
+
2242
+ if (typeof elm.value !== 'undefined') {
2243
+ elm.value = value === null || typeof value === 'undefined' ? '' : String(value);
2244
+ }
2245
+ return true;
2246
+ },
2247
+ listener: function (elm, handler) {
2248
+ if (!elm?.addEventListener || typeof handler !== 'function') {
2249
+ return false;
2250
+ }
2251
+
2252
+ const event_name = get_listener_event(elm);
2253
+ const listener_key = '__xuda_native_bind_listener_' + event_name;
2254
+ if (elm[listener_key]) {
2255
+ elm.removeEventListener(event_name, elm[listener_key]);
2256
+ }
2257
+ elm.addEventListener(event_name, handler);
2258
+ elm[listener_key] = handler;
2259
+ return true;
2260
+ },
2261
+ };
2262
+ };
2263
+ func.runtime.bind.is_valid_adapter = function (adapter) {
2264
+ return !!(
2265
+ adapter &&
2266
+ typeof adapter.getter === 'function' &&
2267
+ typeof adapter.setter === 'function' &&
2268
+ typeof adapter.listener === 'function'
2269
+ );
2270
+ };
2271
+ func.runtime.bind.get_adapter = function (SESSION_ID) {
2272
+ const native_adapter = func.runtime.bind.get_native_adapter();
2273
+ if (func.runtime.session.is_slim(SESSION_ID)) {
2274
+ return native_adapter;
2275
+ }
2276
+
2277
+ const plugin_bind = UI_FRAMEWORK_PLUGIN?.bind;
2278
+ if (!plugin_bind) {
2279
+ return native_adapter;
2280
+ }
2281
+
2282
+ if (func.runtime.bind.is_valid_adapter(plugin_bind)) {
2283
+ return plugin_bind;
2284
+ }
2285
+
2286
+ if (typeof plugin_bind === 'function') {
2287
+ try {
2288
+ const bind_instance = new plugin_bind();
2289
+ if (func.runtime.bind.is_valid_adapter(bind_instance)) {
2290
+ return bind_instance;
2291
+ }
2292
+ } catch (error) {}
2293
+
2294
+ try {
2295
+ const bind_factory = plugin_bind();
2296
+ if (func.runtime.bind.is_valid_adapter(bind_factory)) {
2297
+ return bind_factory;
2298
+ }
2299
+ } catch (error) {}
2300
+ }
2301
+
2302
+ return native_adapter;
2303
+ };
2168
2304
  func.runtime.bind.resolve_field = async function (SESSION_ID, prog_id, dsSessionP, field_id, iterate_info) {
2169
2305
  let _prog_id = prog_id;
2170
2306
  let _dsP = dsSessionP;
@@ -8834,7 +8970,10 @@ func.runtime.ui.find_in_root = function (SESSION_ID, selector) {
8834
8970
  };
8835
8971
  func.runtime.ui.get_root_tag_name = function () {
8836
8972
  let root_tag_name = 'div';
8837
- if (typeof glb.SLIM_BUNDLE === 'undefined' && !glb.SLIM_BUNDLE) {
8973
+ if (!func.runtime.session.is_slim()) {
8974
+ if (typeof UI_FRAMEWORK_PLUGIN?.core !== 'function') {
8975
+ return root_tag_name;
8976
+ }
8838
8977
  const ui_plugin_core = new UI_FRAMEWORK_PLUGIN.core();
8839
8978
  root_tag_name = ui_plugin_core?.rootTagName() || root_tag_name;
8840
8979
  }
@@ -12661,6 +12800,12 @@ func.runtime.ui.close_modal_session = async function (SESSION_ID, modal_id) {
12661
12800
  func.runtime.ui.render_screen_type = async function (options) {
12662
12801
  const $div_content = func.runtime.ui.get_children(options.$div);
12663
12802
  func.runtime.ui.sync_child_parent_container(options.$div);
12803
+ const assert_framework_screen_supported = function (screen_type) {
12804
+ if (!func.runtime.session.is_slim(options.SESSION_ID)) {
12805
+ return;
12806
+ }
12807
+ throw new Error('Slim mode does not support "' + screen_type + '" screens without a UI framework plugin');
12808
+ };
12664
12809
 
12665
12810
  let $ret = options.$div;
12666
12811
  let $nav = func.runtime.ui.get_nav(options.SESSION_ID);
@@ -12668,6 +12813,7 @@ func.runtime.ui.render_screen_type = async function (options) {
12668
12813
 
12669
12814
  switch (options.paramsP.screen_type) {
12670
12815
  case 'modal': {
12816
+ assert_framework_screen_supported('modal');
12671
12817
  params = func.runtime.ui.build_modal_params(options.paramsP, options.$div, options.$container, options.close_modal);
12672
12818
  const modal_id = params.modal_id;
12673
12819
  func.runtime.ui.set_modal_params(options.SESSION_ID, modal_id, params);
@@ -12684,6 +12830,7 @@ func.runtime.ui.render_screen_type = async function (options) {
12684
12830
  }
12685
12831
 
12686
12832
  case 'popover': {
12833
+ assert_framework_screen_supported('popover');
12687
12834
  const xu_popover_controller = func.UI.component.create_app_popover_component(options.SESSION_ID);
12688
12835
  params = func.runtime.ui.build_popover_params(options.paramsP, options.$div, options.$container);
12689
12836
 
@@ -12698,6 +12845,7 @@ func.runtime.ui.render_screen_type = async function (options) {
12698
12845
  }
12699
12846
 
12700
12847
  case 'page': {
12848
+ assert_framework_screen_supported('page');
12701
12849
  const nav = func.runtime.ui.get_first_node($nav);
12702
12850
 
12703
12851
  params = func.runtime.ui.build_page_params(options.SESSION_ID, options.paramsP, $div_content, options.$container, nav);
@@ -17301,7 +17449,7 @@ func.runtime.render.handle_xu_bind = async function (options) {
17301
17449
  return {};
17302
17450
  }
17303
17451
 
17304
- const bind = new UI_FRAMEWORK_PLUGIN.bind();
17452
+ const bind = func.runtime.bind.get_adapter(options.SESSION_ID);
17305
17453
  const field_changed = async function () {
17306
17454
  const _ds = SESSION_OBJ[options.SESSION_ID].DS_GLB[_dsP];
17307
17455
  const field_type = func.runtime.bind.get_field_type(field_prop);
@@ -22359,13 +22507,22 @@ func.index.call_worker = async function (SESSION_ID, obj, params, promiseP) {
22359
22507
  };
22360
22508
 
22361
22509
  func.index.init_SCREEN_BLOCKER = async function (SESSION_ID) {
22510
+ const get_loader = async function () {
22511
+ if (func.runtime.session.is_slim(SESSION_ID) || typeof UI_FRAMEWORK_PLUGIN?.loader !== 'function') {
22512
+ return {
22513
+ dismiss: function () {},
22514
+ };
22515
+ }
22516
+ return await UI_FRAMEWORK_PLUGIN.loader(LOADER_TEXT);
22517
+ };
22518
+
22362
22519
  setInterval(async function () {
22363
22520
  if (glb.CURRENT_APP_LOADING || (!LOADER_ACTIVE && xu_isEmpty(SCREEN_BLOCKER_OBJ))) {
22364
22521
  return;
22365
22522
  }
22366
22523
  glb.CURRENT_APP_LOADING = 1;
22367
22524
 
22368
- const loader = await UI_FRAMEWORK_PLUGIN.loader(LOADER_TEXT);
22525
+ const loader = await get_loader();
22369
22526
 
22370
22527
  glb.CURRENT_APP_LOADING = loader;
22371
22528