@kispace-io/gs-lib 1.0.36 → 1.0.39

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kispace-io/gs-lib",
3
- "version": "1.0.36",
3
+ "version": "1.0.39",
4
4
  "type": "module",
5
5
  "license": "EPL-2.0",
6
6
  "repository": {
package/src/gs-litns.ts CHANGED
@@ -1,213 +1,5 @@
1
- // Lit namespace module - exports all lit APIs for user modules
2
- // Lit is required for gs-ol-adapters (uses lit.render) and for user modules
3
- // WebAwesome is imported here to make it available to user modules (treated as part of lit)
4
-
5
1
  // Re-export all Lit APIs from appspace's externals/lit module - single source of truth
6
- export * from "@kispace-io/appspace/externals/lit-exports";
7
-
8
- // Import specific items needed for defineComponent and lit namespace object
9
- import {
10
- html, css, nothing, svg, LitElement, unsafeCSS,
11
- when, repeat, keyed, classMap, styleMap, ifDefined,
12
- guard, cache, unsafeHTML, until, live, createRef, ref, render
13
- } from "@kispace-io/appspace/externals/lit-exports";
2
+ export * as lit from "@kispace-io/appspace/externals/lit-exports";
14
3
 
15
- // Import WebAwesome components from appspace's externals/webawesome module
16
- // This maintains a single source of truth - Vite will optimize the build to only include what's needed
17
- // WebAwesome is treated as part of lit, so it's always available to user modules
18
4
  import "@kispace-io/appspace/externals/webawesome";
19
5
 
20
- /**
21
- * Helper function to define a custom web component from a simple function.
22
- * Converts a render function into a LitElement-based web component.
23
- * Properties are automatically inferred from the props used in the render function.
24
- *
25
- * @param tagName - The custom element tag name (must contain a hyphen)
26
- * @param renderFn - Function that receives props and returns a Lit template
27
- * @param options - Optional configuration (props defaults, styles, etc.)
28
- * @returns The tag name of the registered component
29
- *
30
- * @example
31
- * ```javascript
32
- * export default function ({lit: {html, css, defineComponent}}) {
33
- * // Simple component - properties inferred from props usage
34
- * defineComponent('my-button', (props) => html`
35
- * <button @click=${props.onClick}>${props.label || 'Click'}</button>
36
- * `);
37
- *
38
- * // Component with default props (auto-converted to properties)
39
- * defineComponent('my-counter', (props) => html`
40
- * <div class="counter">Count: ${props.count}</div>
41
- * `, {
42
- * props: { count: 0, label: '' }, // Simple object - auto-converted
43
- * styles: css`
44
- * .counter { font-weight: bold; }
45
- * `
46
- * });
47
- *
48
- * // Use the component in your template
49
- * return () => html`
50
- * <my-counter count="5"></my-counter>
51
- * `;
52
- * }
53
- * ```
54
- */
55
- const defineComponent = (
56
- tagName: string,
57
- renderFn: (props: any) => any,
58
- options?: {
59
- props?: Record<string, any> | Record<string, { type?: any; reflect?: boolean; attribute?: string | boolean }>;
60
- styles?: any;
61
- shadowRootOptions?: ShadowRootInit;
62
- }
63
- ): string => {
64
- if (!tagName.includes('-')) {
65
- throw new Error(`Custom element tag name must contain a hyphen: ${tagName}`);
66
- }
67
-
68
- // Check if already defined
69
- if (customElements.get(tagName)) {
70
- return tagName;
71
- }
72
-
73
- // Convert simple props object to LitElement property definitions
74
- const convertPropsToProperties = (props: Record<string, any>): Record<string, any> => {
75
- const properties: Record<string, any> = {};
76
-
77
- for (const [key, value] of Object.entries(props)) {
78
- // If it's already a LitElement property config, use it as-is
79
- if (value && typeof value === 'object' && ('type' in value || 'reflect' in value || 'attribute' in value)) {
80
- properties[key] = value;
81
- } else {
82
- // Infer type from default value
83
- const type = value === null || value === undefined ? String
84
- : typeof value === 'boolean' ? Boolean
85
- : typeof value === 'number' ? Number
86
- : typeof value === 'object' ? Object
87
- : String;
88
-
89
- properties[key] = {
90
- type: type,
91
- // Set default value
92
- ...(value !== undefined && { value })
93
- };
94
- }
95
- }
96
-
97
- return properties;
98
- };
99
-
100
- // Determine properties from options
101
- let properties: Record<string, any> = {};
102
- if (options?.props) {
103
- properties = convertPropsToProperties(options.props);
104
- }
105
-
106
- // Track props accessed during render to auto-create properties
107
- // This allows properties to be inferred from render function usage
108
- const accessedProps = new Set<string>();
109
- const propsProxy = new Proxy({ $this: {} }, {
110
- get(_target, prop: string) {
111
- // Track all property accesses except built-ins and $this
112
- if (typeof prop === 'string' &&
113
- prop !== '$this' &&
114
- prop !== 'toJSON' &&
115
- prop !== 'toString' &&
116
- prop !== 'valueOf' &&
117
- !prop.startsWith('Symbol.')) {
118
- accessedProps.add(prop);
119
- }
120
- // Return a safe default value based on common patterns
121
- return prop.endsWith('Handler') || prop.startsWith('on') ? (() => {}) : '';
122
- }
123
- });
124
-
125
- // Do an initial render to detect accessed props
126
- // This is safe because we catch all errors and the render function
127
- // should be pure (no side effects)
128
- try {
129
- renderFn(propsProxy);
130
- } catch {
131
- // Ignore errors during prop detection - render function might
132
- // throw if props are required, but that's okay for detection
133
- }
134
-
135
- // Add auto-detected props that weren't explicitly defined
136
- // Default to String type for auto-detected props
137
- for (const prop of accessedProps) {
138
- if (!(prop in properties)) {
139
- properties[prop] = { type: String };
140
- }
141
- }
142
-
143
- class DynamicComponent extends LitElement {
144
- static properties = properties;
145
-
146
- static styles = options?.styles;
147
-
148
- constructor() {
149
- super();
150
- // Initialize default values from simple props (not LitElement config objects)
151
- if (options?.props) {
152
- for (const [key, value] of Object.entries(options.props)) {
153
- // Only set default if it's a simple value, not a LitElement property config
154
- if (value !== undefined && !(value && typeof value === 'object' && ('type' in value || 'reflect' in value || 'attribute' in value))) {
155
- (this as any)[key] = value;
156
- }
157
- }
158
- }
159
- }
160
-
161
- createRenderRoot() {
162
- if (options?.shadowRootOptions) {
163
- return this.attachShadow(options.shadowRootOptions);
164
- }
165
- return super.createRenderRoot();
166
- }
167
-
168
- render() {
169
- // Create a props object from element properties
170
- const props: any = {
171
- $this: this // Element instance - needed for arrow functions which don't have 'this'
172
- };
173
-
174
- // Copy all properties to props object
175
- for (const key of Object.keys(properties)) {
176
- props[key] = (this as any)[key];
177
- }
178
-
179
- // Bind render function to this element so 'this' refers to the element instance
180
- // Note: 'this' works for regular functions, 'props.$this' works for arrow functions
181
- return renderFn.call(this, props);
182
- }
183
- }
184
-
185
- // Register the custom element
186
- customElements.define(tagName, DynamicComponent);
187
-
188
- return tagName;
189
- };
190
-
191
- // Export all lit APIs as a namespace object
192
- export const lit = {
193
- html,
194
- css,
195
- unsafeCSS,
196
- svg,
197
- nothing,
198
- when,
199
- repeat,
200
- keyed,
201
- classMap,
202
- styleMap,
203
- ifDefined,
204
- guard,
205
- cache,
206
- unsafeHTML,
207
- until,
208
- live,
209
- ref,
210
- createRef,
211
- defineComponent
212
- };
213
-