@dooboostore/dom-render 1.0.102 → 1.0.103

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 (57) hide show
  1. package/DomRender.d.ts +21 -6
  2. package/DomRender.js +54 -23
  3. package/DomRenderProxy.d.ts +7 -3
  4. package/DomRenderProxy.js +120 -49
  5. package/README.MD +380 -65
  6. package/components/ComponentBase.d.ts +11 -9
  7. package/components/ComponentBase.js +41 -14
  8. package/components/ComponentSet.d.ts +2 -2
  9. package/components/appender/Appender.d.ts +2 -2
  10. package/components/checkbox/CheckBox.d.ts +4 -4
  11. package/components/choose/Choose.d.ts +4 -4
  12. package/components/choose/Choose.js +0 -16
  13. package/components/details/Details.d.ts +5 -5
  14. package/components/forOf/ForOf.d.ts +2 -2
  15. package/components/if/If.d.ts +2 -2
  16. package/components/index.d.ts +26 -24
  17. package/components/index.js +2 -1
  18. package/components/input/Input.d.ts +2 -2
  19. package/components/input/Input.js +27 -24
  20. package/components/promise/PromiseSwitch.d.ts +6 -6
  21. package/components/promise/PromiseSwitch.js +15 -0
  22. package/components/radio/Radio.d.ts +4 -4
  23. package/components/router/Route.d.ts +32 -0
  24. package/components/router/Route.js +116 -0
  25. package/components/select/Select.d.ts +3 -3
  26. package/components/select/Select.js +2 -2
  27. package/components/this/This.d.ts +9 -2
  28. package/components/this/This.js +24 -2
  29. package/components/timer/Timer.d.ts +2 -2
  30. package/configs/Config.d.ts +6 -1
  31. package/decorators/DomRenderNoProxy.d.ts +2 -0
  32. package/decorators/DomRenderNoProxy.js +15 -0
  33. package/dist/bundle.js +2 -0
  34. package/events/EventManager.d.ts +16 -4
  35. package/events/EventManager.js +320 -140
  36. package/index.d.ts +48 -1
  37. package/index.js +40 -0
  38. package/lifecycle/OnDestroyRender.d.ts +1 -1
  39. package/lifecycle/OnProxyDomRender.d.ts +1 -0
  40. package/lifecycle/OnProxyDomRender.js +1 -1
  41. package/operators/DrForOf.js +2 -1
  42. package/operators/DrIf.js +3 -2
  43. package/operators/DrTargetElement.js +2 -1
  44. package/operators/DrTargetElementIsElement.d.ts +0 -5
  45. package/operators/DrTargetElementIsElement.js +2 -1
  46. package/operators/DrThis.js +40 -11
  47. package/operators/OperatorExecuter.js +3 -1
  48. package/package.json +5 -4
  49. package/rawsets/Attrs.d.ts +2 -0
  50. package/rawsets/RawSet.d.ts +2 -2
  51. package/rawsets/RawSet.js +48 -33
  52. package/routers/HashRouter.d.ts +5 -4
  53. package/routers/HashRouter.js +8 -5
  54. package/routers/PathRouter.d.ts +5 -4
  55. package/routers/PathRouter.js +6 -4
  56. package/routers/Router.d.ts +22 -8
  57. package/routers/Router.js +44 -24
package/README.MD CHANGED
@@ -1,6 +1,6 @@
1
1
  DOM-RENDER
2
2
  ===
3
- [![typescript](https://img.shields.io/badge/-npm-black?logo=npm)](https://www.npmjs.com/package/dom-render) [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE.md)
3
+ [![typescript](https://img.shields.io/badge/-npm-black?logo=npm)](https://www.npmjs.com/package/@dooboostore/dom-render) [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE.md)
4
4
  * view template engine
5
5
  * Dom control and reorder and render
6
6
  * all internal variables are managed by proxy. (DomRenderProxy)
@@ -111,7 +111,7 @@ export class IndexComponent implements OnInitRender, OnDestroyRender, OnInit, On
111
111
  ```
112
112
  ```css
113
113
  .#uuid# {
114
- color:${@this@.color}$;
114
+ color:${@this@.color}$ ;
115
115
  }
116
116
  ```
117
117
  ```css
@@ -394,6 +394,40 @@ export class MyComponent extends ComponentBase<{ 'title': string, 'show-icon': s
394
394
  ```
395
395
  When attributes change, the `converter` function will be executed before the value is assigned to the property. For `showIcon`, the string `"true"` or `"false"` will be converted to a boolean. For `createdAt`, the date string will be converted to a `Date` object.
396
396
 
397
+ ### Binding to Methods
398
+
399
+ The `@attribute` decorator can also be applied to methods. When the corresponding HTML attribute changes, the decorated method will be invoked with the new attribute value as its argument. This allows you to execute custom logic directly in response to attribute changes.
400
+
401
+ **Component (`MyComponent.ts`) - Method Example**
402
+ ```typescript
403
+ import { ComponentBase, attribute } from '@dooboostore/dom-render';
404
+
405
+ export class MyComponent extends ComponentBase<{ 'data-value': string }> {
406
+ public receivedData: string = '';
407
+
408
+ @attribute({ name: 'data-value' })
409
+ onDataValueChange(newValue: string): void {
410
+ this.receivedData = `Method received: ${newValue}`;
411
+ console.log(this.receivedData);
412
+ }
413
+ }
414
+ ```
415
+
416
+ **Template (`index.html`) - Method Example**
417
+ ```html
418
+ <my-component data-value="initial"></my-component>
419
+
420
+ <p>${@this@.receivedData}$</p>
421
+
422
+ <script>
423
+ setTimeout(() => {
424
+ const comp = document.querySelector('my-component');
425
+ comp.setAttribute('data-value', 'updated value');
426
+ }, 1000);
427
+ </script>
428
+ ```
429
+ When `data-value` attribute changes, the `onDataValueChange` method will be called with the new value.
430
+
397
431
  </details>
398
432
 
399
433
  ## Element Query with `@query` decorator
@@ -558,6 +592,49 @@ dr-value-link: <input type="text" dr-value-link="@this@.office.addr.street"> <br
558
592
  ```
559
593
  </details>
560
594
 
595
+ ## Element State Attributes
596
+ <details>
597
+ <summary>dr-checked, dr-selected, dr-readonly, dr-disabled<strong>🔻(click)</strong></summary>
598
+
599
+ These attributes allow you to bind boolean values directly to the `checked`, `selected`, `readonly`, and `disabled` properties of HTML elements.
600
+
601
+ * `dr-checked`: Binds the `checked` attribute of an input (checkbox/radio) to a boolean value.
602
+ * `dr-selected`: Binds the `selected` attribute of an option to a boolean value.
603
+ * `dr-readonly`: Binds the `readonly` attribute of an input to a boolean value.
604
+ * `dr-disabled`: Binds the `disabled` attribute of an input/button/etc. to a boolean value.
605
+
606
+ ### Example
607
+
608
+ ```html
609
+ <!-- Example for dr-checked -->
610
+ <input type="checkbox" dr-checked="@this@.isChecked">
611
+ <p>Checkbox is: ${@this@.isChecked}$</p>
612
+
613
+ <!-- Example for dr-selected -->
614
+ <select>
615
+ <option value="apple" dr-selected="@this@.isAppleSelected">Apple</option>
616
+ <option value="banana" dr-selected="@this@.isBananaSelected">Banana</option>
617
+ </select>
618
+
619
+ <!-- Example for dr-readonly -->
620
+ <input type="text" dr-readonly="@this@.isReadOnly" value="Some text">
621
+
622
+ <!-- Example for dr-disabled -->
623
+ <button dr-disabled="@this@.isDisabled">Click Me</button>
624
+ <input type="text" dr-disabled="@this@.isDisabled" value="Disabled input">
625
+ ```
626
+ ```typescript
627
+ class Data {
628
+ isChecked = true;
629
+ isAppleSelected = false;
630
+ isBananaSelected = true;
631
+ isReadOnly = false;
632
+ isDisabled = true;
633
+ }
634
+ // ... DomRender.run(new Data(), ...)
635
+ ```
636
+ </details>
637
+
561
638
  ## dr-on-rendered-init
562
639
  - rendered call
563
640
 
@@ -587,7 +664,7 @@ dr-value-link: <input type="text" dr-value-link="@this@.office.addr.street"> <br
587
664
  <summary>dr-style<strong>🔻(click)</strong></summary>
588
665
 
589
666
  ```html
590
- <div dr-style="{'background-image': 'url(\''+@this@.my?.image+'\')'}" >aa</div>
667
+ <div dr-style="{'background-image': 'url(\' '+@this@.my?.image+'\')'}" >aa</div>
591
668
  <div dr-style="{fontSize: @this@.age + 'px'}"> style </div>
592
669
  <div dr-style="{'font-size': '20px'}"> style</div>
593
670
  <div dr-style="'font-size: ' + @this@.age +'px; margin: ' + @this@.age + 'px'"> style </div>
@@ -682,7 +759,6 @@ DomRender.run(data, document.querySelector('#app')!);
682
759
  ```
683
760
  <!-- 💥 submit call -->
684
761
  <!-- console: {name: 'name data', age: 'age data'} -->
685
- ```
686
762
  </details>
687
763
 
688
764
  <details>
@@ -721,7 +797,6 @@ class FormDataWithValidator {
721
797
  const data = new FormDataWithValidator();
722
798
  DomRender.run(data, document.querySelector('#app')!);
723
799
  ```
724
- ```
725
800
  validator
726
801
  - Validator (abstract)
727
802
  - ValidatorArray (abstract)
@@ -762,88 +837,328 @@ validator
762
837
 
763
838
  ## Route
764
839
  <details>
765
- <summary>Route<strong>🔻(click)</strong></summary>
840
+ <summary><strong>Route (click)</strong></summary>
841
+
842
+ Declarative routing is supported using the `dr-route-match` and `dr-route-regexp` components. This allows you to conditionally render parts of your UI based on the current URL path.
766
843
 
767
- - [examples](./examples/router)
844
+ - [Example](./examples/route)
845
+
846
+ ### 1. Configuration
847
+
848
+ To enable routing, you must set the `routerType` in your `DomRender` configuration.
849
+
850
+ - `routerType`: Can be `'hash'`, `'path'`, or `'none'` (default).
768
851
 
769
- * config routerType: 'hash' | 'path' | 'none' (default: 'none')
770
852
  ```typescript
771
- // Config
772
- const config: Config = {
773
- window
853
+ // In your main setup file (e.g., index.ts)
854
+ import { DomRender, DomRenderRunConfig } from '@dooboostore/dom-render';
855
+
856
+ // ... your root object class (e.g., Index)
857
+
858
+ const config: DomRenderRunConfig<Index> = {
859
+ window: window,
860
+ routerType: 'path' // or 'hash'
774
861
  };
775
- config.targetElements = [
776
- DomRender.createComponent({type: Main, tagName: 'page-main', template: MainTemplate}),
777
- DomRender.createComponent({type: Second, tagName: 'page-second', template: SecondTemplate}),
778
- DomRender.createComponent({type: Detail, tagName: 'page-detail', template: DetailTemplate})
779
- ]
780
- config.routerType = 'hash'; // 'hash' | 'path' | 'none';
781
- const data = DomRender.run(new Data(), document.querySelector('#app')!, config);
862
+
863
+ const domRender = new DomRender({
864
+ rootObject: new Index(),
865
+ target: document.querySelector('#app')!,
866
+ config: config
867
+ }, {autoGo: '/'}); // autoGo navigates to the initial path
782
868
  ```
869
+
870
+ ### 2. Template Usage
871
+
872
+ Use the `<dr-route-match>` and `<dr-route-regexp>` components in your HTML template to define which content appears for which route.
873
+
874
+ - **`<dr-route-match>`**: Renders its content when the path matches the `value` attribute. It supports simple paths and path parameters (e.g., `/{id}`).
875
+ - **`<dr-route-regexp>`**: Renders its content when the path matches the regular expression in the `value` attribute.
876
+
783
877
  ```html
878
+ <!-- index.html -->
784
879
  <header>
785
- <h1>examples header</h1>
786
- <h2>${@this@.name}$</h2>
787
- <div>
788
- <div><button dr-event-click="$router.go('/')">main</button></div>
789
- <div>
790
- <button dr-event-click="$router.go('/second', {secondata: 555})">second</button>
791
- <button dr-event-click="$router.go('/second/5')">second/1</button>
792
- <button dr-event-click="$router.go('/second/wow')">second/2</button>
793
- </div>
794
- <div><button dr-event-click="$router.go('/detail/25?name=zzz')">detail</button></div>
795
- </div>
880
+ <!-- Navigation buttons -->
881
+ <button dr-event-click="$router?.go({path:'/'})">Main</button>
882
+ <button dr-event-click="$router?.go({path:'/second'})">Second</button>
883
+ <button dr-event-click="$router?.go({path:'/detail/42'})">Detail 42</button>
796
884
  </header>
797
- <hr>
885
+
798
886
  <main>
799
- <page-main dr-if="$router.test('/')"></page-main>
800
- <page-second dr-if="$router.test('/second')">1</page-second>
801
- <page-second dr-if="$router.testRegexp('/second/[0-9]?$')">2</page-second>
802
- <page-second dr-if="$router.testRegexp('/second/wow$')">wow</page-second>
803
- <page-detail url='/detail/{id:[0-9]+}' dr-if="$router.test($attribute.url)" dr-on-create:callback="$component.routerData($router.getRouteData($attribute.url))" ></page-detail>
804
- <div>
805
- <button dr-event-click="@this@.plusCount()">${@this@.count}$ count pluse++</button>
806
- </div>
887
+ <!-- Content for the root path -->
888
+ <dr-route-match value="/">
889
+ <h1>Main Page</h1>
890
+ </dr-route-match>
891
+
892
+ <!-- Content for the /second path -->
893
+ <dr-route-match value="/second">
894
+ <h1>Second Page</h1>
895
+ </dr-route-match>
896
+
897
+ <!-- Content for a path with a numeric parameter -->
898
+ <dr-route-match value="/detail/{id:[0-9]+}">
899
+ <h1>Detail Page</h1>
900
+ <p>The router's pathData will contain the matched 'id'.</p>
901
+ </dr-route-match>
902
+
903
+ <!-- Content using a regular expression -->
904
+ <dr-route-regexp value="/second/[0-9]?$">
905
+ <p>This content appears for paths like /second/1, /second/2, etc.</p>
906
+ </dr-route-regexp>
807
907
  </main>
808
- <hr>
809
- <footer>footer</footer>
810
908
  ```
909
+
910
+ The `$router` object is automatically available in your templates for navigation (`$router.go(...)`) and testing (`$router.test(...)`).
911
+
912
+ </details>
913
+
914
+ ## Accessing the Root Object Proxy
915
+
916
+ After initializing `DomRender`, you can get a proxied reference to your `rootObject`. Any changes made to this proxy will be automatically detected and reflected in the DOM. This is useful for updating state from outside your component's methods, such as in `setTimeout` or in response to external events.
917
+
811
918
  ```typescript
812
- export class Second implements OnCreateRender {
813
- name = 'Second'
919
+ import { DomRender } from '@dooboostore/dom-render';
920
+
921
+ class App {
922
+ message = 'Hello, World!';
923
+ }
924
+
925
+ // 1. Initialize DomRender
926
+ const domRender = new DomRender({
927
+ rootObject: new App(),
928
+ target: document.querySelector('#app')!
929
+ });
930
+
931
+ // 2. Get the proxy to the rootObject
932
+ const data = domRender.rootObject;
933
+
934
+ // 3. Now you can modify the state from anywhere
935
+ setTimeout(() => {
936
+ // This change will automatically update the UI
937
+ data.message = 'Hello, DomRender!';
938
+ }, 2000);
939
+ ```
940
+
941
+ ```html
942
+ <!-- index.html -->
943
+ <div id="app">
944
+ ${@this@.message}$
945
+ </div>
946
+ ```
947
+
948
+ ## Core Components
949
+ This section describes the built-in components provided by `dom-render`.
950
+
951
+ <details>
952
+ <summary><strong>ComponentBase & Decorators (<code>@attribute</code>, <code>@query</code>, <code>@event</code>)</strong>🔻(click)</summary>
953
+
954
+ `ComponentBase` is the foundation for creating custom components that can interact with the `dom-render` lifecycle and attributes. When you extend `ComponentBase`, you gain access to powerful decorators for linking your class to the template.
955
+
956
+ - **`@attribute`**: Binds a class property to an HTML attribute. It can automatically convert values and even bind to methods.
957
+ - **`@query`**: Injects DOM elements from your component's template into class properties or method arguments.
958
+ - **`@event`**: Binds a class method to a DOM event on an element within the template, handling listener cleanup automatically.
959
+
960
+ *For detailed examples of these decorators, please see their dedicated sections above in the documentation.*
814
961
 
815
- onCreateRender(data: CreatorMetaData): void {
816
- console.log('----->', data.router)
962
+ </details>
963
+
964
+ <details>
965
+ <summary><strong>ComponentSet</strong>🔻(click)</summary>
966
+
967
+ `ComponentSet` is a wrapper class that pairs a component instance with its own template and styles. It's the primary mechanism for dynamically rendering and swapping components within a `dr-this` block.
968
+
969
+ ### Usage
970
+ ```typescript
971
+ import { ComponentSet } from '@dooboostore/dom-render';
972
+
973
+ // Define two simple components
974
+ class ComponentA { message = 'This is Component A'; }
975
+ class ComponentB { message = 'Now you see Component B'; }
976
+
977
+ class App {
978
+ // Create ComponentSet instances for each component
979
+ componentA = new ComponentSet(new ComponentA(), { template: '<h1>${@this@.message}$</h1>' });
980
+ componentB = new ComponentSet(new ComponentB(), { template: '<h2>${@this@.message}$</h2>' });
981
+
982
+ // This property will hold the currently active component
983
+ activeComponent: ComponentSet;
984
+
985
+ constructor() {
986
+ this.activeComponent = this.componentA;
817
987
  }
988
+
989
+ showA() { this.activeComponent = this.componentA; }
990
+ showB() { this.activeComponent = this.componentB; }
818
991
  }
819
992
  ```
993
+
994
+ ```html
995
+ <!-- This div will dynamically render the component held by 'activeComponent' -->
996
+ <div dr-this="@this@.activeComponent"></div>
997
+
998
+ <button dr-event-click="@this@.showA()">Show Component A</button>
999
+ <button dr-event-click="@this@.showB()">Show Component B</button>
1000
+ ```
1001
+ </details>
1002
+
1003
+ <details>
1004
+ <summary><strong><code>dr-this</code></strong>🔻(click)</summary>
1005
+
1006
+ The `dr-this` component is the target for rendering a `ComponentSet`. It dynamically renders the component instance and template defined in the `ComponentSet` object it's bound to.
1007
+
1008
+ See the `ComponentSet` example above for a practical demonstration.
1009
+
1010
+ </details>
1011
+
1012
+ <details>
1013
+ <summary><strong><code>dr-choose</code> / <code>dr-choose-when</code> / <code>dr-choose-other-wise</code></strong>🔻(click)</summary>
1014
+
1015
+ Provides a "switch-case" control flow for rendering blocks of HTML. It evaluates a data object and renders the first `dr-choose-when` block whose `test` condition returns true. If no `when` blocks match, the `dr-choose-other-wise` block is rendered.
1016
+
1017
+ ### Usage
820
1018
  ```typescript
821
- import {RouteData} from 'dom-render/routers/Router';
822
- import {OnCreateRender} from 'dom-render/lifecycle/OnCreateRender';
1019
+ class App {
1020
+ status: 'loading' | 'success' | 'error' = 'loading';
1021
+ }
1022
+ ```
1023
+ ```html
1024
+ <dr-choose data="${@this@.status}$">
1025
+ <dr-choose-when test="(status) => status === 'loading'">
1026
+ <p>Loading...</p>
1027
+ </dr-choose-when>
1028
+ <dr-choose-when test="(status) => status === 'success'">
1029
+ <p>Data loaded successfully!</p>
1030
+ </dr-choose-when>
1031
+ <dr-choose-other-wise>
1032
+ <p>An unknown error occurred.</p>
1033
+ </dr-choose-other-wise>
1034
+ </dr-choose>
1035
+ ```
1036
+ </details>
823
1037
 
824
- export class Detail implements OnCreateRender {
825
- name = 'Detail';
1038
+ <details>
1039
+ <summary><strong><code>dr-promise-switch</code></strong>🔻(click)</summary>
826
1040
 
827
- onCreateRender(data: CreatorMetaData) {
828
- console.log('routeData->', data);
829
- }
1041
+ Declaratively handles the different states of a JavaScript `Promise`. It provides child components to render content for `pending`, `fulfilled`, and `rejected` states.
830
1042
 
831
- routerData(routeData: RouteData) {
832
- console.log('--------', routeData);
833
- }
1043
+ ### Child Components
1044
+ - `<dr-promise-switch-pending>`: Shown while the promise is in flight.
1045
+ - `<dr-promise-switch-fulfilled>`: Shown when the promise resolves successfully. The resolved data is available inside via `#component#.data`.
1046
+ - `<dr-promise-switch-rejected>`: Shown when the promise is rejected. The error is available inside via `#component#.data`.
1047
+ - `<dr-promise-switch-default>`: Shown before the promise is triggered.
1048
+
1049
+ ### Usage
1050
+ ```typescript
1051
+ class App {
1052
+ userPromise = null;
1053
+
1054
+ fetchUser() {
1055
+ this.userPromise = fetch('/api/user').then(res => res.json());
1056
+ }
834
1057
  }
835
1058
  ```
1059
+ ```html
1060
+ <button dr-event-click="@this@.fetchUser()">Fetch User</button>
1061
+
1062
+ <dr-promise-switch data="${@this@.userPromise}$">
1063
+ <dr-promise-switch-pending>
1064
+ <p>Fetching user data...</p>
1065
+ </dr-promise-switch-pending>
1066
+ <dr-promise-switch-fulfilled>
1067
+ <p>Welcome, ${#component#.data.name}$!</p>
1068
+ </dr-promise-switch-fulfilled>
1069
+ <dr-promise-switch-rejected>
1070
+ <p>Failed to fetch user: ${#component#.data.message}$</p>
1071
+ </dr-promise-switch-rejected>
1072
+ </dr-promise-switch>
1073
+ ```
1074
+ </details>
1075
+
1076
+ <details>
1077
+ <summary><strong><code>dr-checkbox</code></strong>🔻(click)</summary>
1078
+
1079
+ A wrapper for creating a custom, stylable checkbox. It uses child components to define the appearance for checked and unchecked states.
1080
+
1081
+ ### Child Components
1082
+ - `<dr-checkbox-checked>`: Content to show when the box is checked.
1083
+ - `<dr-checkbox-unchecked>`: Content to show when the box is unchecked.
1084
+
1085
+ ### Usage
1086
+ ```typescript
1087
+ class App {
1088
+ agreed = false;
1089
+ }
1090
+ ```
1091
+ ```html
1092
+ <dr-checkbox name="terms" checked="${@this@.agreed}$" change="${(checked) => @this@.agreed = checked}$">
1093
+ <dr-checkbox-checked>
1094
+ <!-- Using FontAwesome icons as an example -->
1095
+ <i class="fas fa-check-square"></i> I agree to the terms.
1096
+ </dr-checkbox-checked>
1097
+ <dr-checkbox-unchecked>
1098
+ <i class="far fa-square"></i> I agree to the terms.
1099
+ </dr-checkbox-unchecked>
1100
+ </dr-checkbox>
1101
+
1102
+ <p>Agreed: ${@this@.agreed}$</p>
1103
+ ```
1104
+ </details>
1105
+
1106
+ <details>
1107
+ <summary><strong><code>dr-details</code></strong>🔻(click)</summary>
1108
+
1109
+ An enhanced version of the native `<details>` element. It provides child components for the summary and body, and includes extra functionality like closing when the user clicks outside of it.
1110
+
1111
+ ### Child Components
1112
+ - `<dr-details-summary>`: The clickable header of the details element.
1113
+ - `<dr-details-body>`: The collapsible content.
1114
+ - `<dr-details-form>`: A special body that is a form, with features like automatic reset on toggle.
1115
+
1116
+ ### Usage
1117
+ ```html
1118
+ <dr-details>
1119
+ <dr-details-summary>
1120
+ <h3>More Information</h3>
1121
+ </dr-details-summary>
1122
+ <dr-details-body>
1123
+ <p>Here is the hidden content that appears on click.</p>
1124
+ </dr-details-body>
1125
+ </dr-details>
1126
+ ```
1127
+ </details>
836
1128
 
1129
+ <details>
1130
+ <summary><strong><code>dr-input</code></strong>🔻(click)</summary>
1131
+
1132
+ A custom input component that enhances a standard `<input>` with powerful features like debouncing and distinct value change detection. This is useful for performance-intensive tasks like live search.
1133
+
1134
+ ### Attributes
1135
+ - `debounceTime`: (Optional) The time in milliseconds to wait after the user stops typing before firing the `input` event.
1136
+ - `distinct`: (Optional) If set to `true`, the `input` event will only fire if the new value is different from the previous one.
1137
+ - `input`: A callback function that receives the debounced/distinct value.
1138
+
1139
+ ### Usage
837
1140
  ```typescript
838
- // RouteData type
839
- type RouteData = {
840
- path: string;
841
- url: string;
842
- data?: any;
843
- searchParams: URLSearchParams;
844
- pathData?: any;
1141
+ class App {
1142
+ searchQuery = '';
1143
+
1144
+ handleSearch(query: string) {
1145
+ console.log('Searching for:', query);
1146
+ this.searchQuery = query;
1147
+ }
845
1148
  }
846
1149
  ```
1150
+ ```html
1151
+ <label>Search:</label>
1152
+ <dr-input
1153
+ type="text"
1154
+ class="search-input"
1155
+ debounceTime="300"
1156
+ distinct="true"
1157
+ input="${(value) => @this@.handleSearch(value)}$"
1158
+ ></dr-input>
1159
+
1160
+ <p>Current query: ${@this@.searchQuery}$</p>
1161
+ ```
847
1162
  </details>
848
1163
 
849
1164
  ## Messenger (Data transmission)
@@ -908,7 +1223,7 @@ const rangeArray = new Range(100,55, 10).toArray();
908
1223
  const appender = new Appender<number>([1, 2]);
909
1224
  appender.push(3, 4)
910
1225
  for (const data of appender) {
911
- console.log('----appender item--->', data);
1226
+ console.log('----appender item---', data);
912
1227
  }
913
1228
  ```
914
1229
  </details>
@@ -922,10 +1237,10 @@ for (const data of appender) {
922
1237
  {
923
1238
  name: 'dom-render'
924
1239
  onBeforeReturnSet: (name: string, value: any, fullpath: string[]) => {
925
- console.log('set name-->', name, value, fullpath);
1240
+ console.log('set name--', name, value, fullpath);
926
1241
  }
927
1242
  onBeforeReturnGet: (name: string, value: any, fullpath: string[]) => {
928
- console.log('get name-->', name, value, fullpath);
1243
+ console.log('get name--', name, value, fullpath);
929
1244
  }
930
1245
  }
931
1246
  ```
@@ -1149,4 +1464,4 @@ lazy loading rollup config
1149
1464
 
1150
1465
  # License
1151
1466
  * MIT
1152
- * visualkhh@gmail.com
1467
+ * visualkhh@gmail.com
@@ -8,27 +8,31 @@ import { OnInitRender } from '../lifecycle/OnInitRender';
8
8
  import { OnDestroyRender, OnDestroyRenderParams } from '../lifecycle/OnDestroyRender';
9
9
  import { OnDrThisUnBind } from '../lifecycle/dr-this/OnDrThisUnBind';
10
10
  import { OnDrThisBind } from '../lifecycle/dr-this/OnDrThisBind';
11
- import * as Render from '../rawsets/Render';
11
+ import type { Render } from '../rawsets/Render';
12
12
  export declare const ATTRIBUTE_METADATA_KEY: unique symbol;
13
13
  export declare const QUERY_METADATA_KEY: unique symbol;
14
14
  export declare const EVENT_METADATA_KEY: unique symbol;
15
15
  export declare function attribute(options?: {
16
16
  name?: string;
17
17
  converter?: (value: string | null) => any;
18
- }): PropertyDecorator;
18
+ }): (target: object, propertyKey: string | symbol, descriptor?: PropertyDescriptor) => void;
19
19
  export declare function query(selector: string): (target: object, propertyKey: string | symbol, descriptor?: PropertyDescriptor) => void;
20
20
  export declare function event(options: {
21
21
  query: string;
22
22
  name: string;
23
23
  }): MethodDecorator;
24
- export declare abstract class ComponentBase<T> implements OnChangeAttrRender, OnCreateRenderData, OnCreatedThisChild, OnDrThisBind, OnDrThisUnBind, OnInitRender, OnDestroyRender {
25
- private config?;
24
+ export type ComponentBaseConfig = {
25
+ onlyParentType?: ConstructorType<any>[] | ConstructorType<any>;
26
+ };
27
+ export declare class ComponentBase<T = any, C extends ComponentBaseConfig = ComponentBaseConfig> implements OnChangeAttrRender, OnCreateRenderData, OnCreatedThisChild, OnDrThisBind, OnDrThisUnBind, OnInitRender, OnDestroyRender {
28
+ private _config?;
26
29
  private _rawSet?;
27
30
  private _children;
28
31
  private _render;
29
32
  private _attribute?;
30
33
  private _boundEventListeners;
31
- get render(): Render.Render | undefined;
34
+ get componentConfig(): C;
35
+ get render(): Render | undefined;
32
36
  get rawSet(): RawSet | undefined;
33
37
  private _queryElements;
34
38
  private _cleanupEventListeners;
@@ -42,9 +46,7 @@ export declare abstract class ComponentBase<T> implements OnChangeAttrRender, On
42
46
  getParentThis<P>(): P;
43
47
  getChildren<C extends ConstructorType<any>>(type: C): InstanceType<C>[];
44
48
  getChildren<C extends ConstructorType<any>[]>(types: C): InstanceType<C[number]>[];
45
- constructor(config?: {
46
- onlyParentType: ConstructorType<any>[] | ConstructorType<any>;
47
- });
49
+ constructor(_config?: C);
48
50
  private setRawSet;
49
51
  setAttribute(attribute: T): void;
50
52
  onCreatedThisChild(child: any, data: OnCreateRenderDataParams): void;
@@ -53,6 +55,6 @@ export declare abstract class ComponentBase<T> implements OnChangeAttrRender, On
53
55
  onInitRender(param: any, rawSet: RawSet): void;
54
56
  onDrThisBind(): void;
55
57
  onDrThisUnBind(): void;
56
- onDestroyRender(data: OnDestroyRenderParams): void;
58
+ onDestroyRender(data?: OnDestroyRenderParams): void;
57
59
  }
58
60
  //# sourceMappingURL=ComponentBase.d.ts.map