@eduboxpro/studio 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/LICENSE +21 -0
- package/README.md +70 -0
- package/fesm2022/eduboxpro-studio.mjs +220 -0
- package/fesm2022/eduboxpro-studio.mjs.map +1 -0
- package/index.d.ts +148 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 EduBoxPro Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @eduboxpro/studio
|
|
2
|
+
|
|
3
|
+
Modern Angular UI component library for educational platforms with a fully customizable design system.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @eduboxpro/studio
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### 1. Import Styles
|
|
14
|
+
|
|
15
|
+
Add to your `angular.json`:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"styles": [
|
|
20
|
+
"node_modules/@eduboxpro/studio/styles/studio.scss"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### 2. Configure Provider
|
|
26
|
+
|
|
27
|
+
In your `app.config.ts`:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { provideStudioConfig } from '@eduboxpro/studio/config';
|
|
31
|
+
|
|
32
|
+
export const appConfig: ApplicationConfig = {
|
|
33
|
+
providers: [
|
|
34
|
+
provideStudioConfig({
|
|
35
|
+
theme: {
|
|
36
|
+
mode: 'light',
|
|
37
|
+
colors: { primary: '#3b82f6' }
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 3. Use Components
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { ButtonComponent } from '@eduboxpro/studio/primitives';
|
|
48
|
+
|
|
49
|
+
@Component({
|
|
50
|
+
imports: [ButtonComponent],
|
|
51
|
+
template: `<studio-button (clicked)="handleClick()">Click me</studio-button>`
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
- **Modern Angular 20+** - Standalone components, signals
|
|
58
|
+
- **Fully Customizable** - JSON-based design system
|
|
59
|
+
- **Dark Theme** - Built-in light/dark modes
|
|
60
|
+
- **Type Safe** - 100% TypeScript
|
|
61
|
+
- **Tree-shakeable** - Optimized bundle size
|
|
62
|
+
- **Zero Dependencies** - Only Angular core
|
|
63
|
+
|
|
64
|
+
## Documentation
|
|
65
|
+
|
|
66
|
+
Full documentation: https://github.com/eduboxpro/studio
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
MIT © EduBoxPro Team
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, inject, signal, effect, Injectable, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, input, output, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { DOCUMENT } from '@angular/common';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Injection token for Studio configuration
|
|
7
|
+
*/
|
|
8
|
+
const STUDIO_CONFIG = new InjectionToken('STUDIO_CONFIG', {
|
|
9
|
+
providedIn: 'root',
|
|
10
|
+
factory: () => ({})
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
class StudioConfigService {
|
|
14
|
+
document = inject(DOCUMENT);
|
|
15
|
+
config = signal({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
16
|
+
themeMode = signal('light', ...(ngDevMode ? [{ debugName: "themeMode" }] : []));
|
|
17
|
+
constructor() {
|
|
18
|
+
effect(() => {
|
|
19
|
+
this.applyTheme(this.config().theme);
|
|
20
|
+
}, { allowSignalWrites: false });
|
|
21
|
+
}
|
|
22
|
+
configure(config) {
|
|
23
|
+
this.config.set(config);
|
|
24
|
+
if (config.theme?.mode) {
|
|
25
|
+
this.setThemeMode(config.theme.mode);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
setThemeMode(mode) {
|
|
29
|
+
this.themeMode.set(mode);
|
|
30
|
+
this.document.documentElement.setAttribute('data-theme', mode);
|
|
31
|
+
}
|
|
32
|
+
toggleTheme() {
|
|
33
|
+
const newMode = this.themeMode() === 'light' ? 'dark' : 'light';
|
|
34
|
+
this.setThemeMode(newMode);
|
|
35
|
+
}
|
|
36
|
+
async loadFromBackend(organizationSlug) {
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(`/api/organizations/${organizationSlug}/design-config`);
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
41
|
+
}
|
|
42
|
+
const config = await response.json();
|
|
43
|
+
this.configure(config);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error('[Studio] Failed to load config from backend:', error);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
applyTheme(theme) {
|
|
51
|
+
if (!theme)
|
|
52
|
+
return;
|
|
53
|
+
const root = this.document.documentElement;
|
|
54
|
+
if (theme.colors) {
|
|
55
|
+
this.applyTokens(root, 'studio', theme.colors);
|
|
56
|
+
}
|
|
57
|
+
if (theme.spacing) {
|
|
58
|
+
this.applyTokens(root, 'studio-spacing', theme.spacing);
|
|
59
|
+
}
|
|
60
|
+
if (theme.borderRadius) {
|
|
61
|
+
this.applyTokens(root, 'studio-radius', theme.borderRadius);
|
|
62
|
+
}
|
|
63
|
+
if (theme.shadows) {
|
|
64
|
+
this.applyTokens(root, 'studio-shadow', theme.shadows);
|
|
65
|
+
}
|
|
66
|
+
if (theme.typography?.fontFamily) {
|
|
67
|
+
root.style.setProperty('--studio-font-family', theme.typography.fontFamily);
|
|
68
|
+
}
|
|
69
|
+
if (theme.typography?.fontSize) {
|
|
70
|
+
this.applyTokens(root, 'studio-font-size', theme.typography.fontSize);
|
|
71
|
+
}
|
|
72
|
+
if (theme.typography?.fontWeight) {
|
|
73
|
+
this.applyTokens(root, 'studio-font-weight', theme.typography.fontWeight);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
applyTokens(root, prefix, tokens) {
|
|
77
|
+
Object.entries(tokens).forEach(([key, value]) => {
|
|
78
|
+
if (value !== undefined && value !== null) {
|
|
79
|
+
root.style.setProperty(`--${prefix}-${key}`, String(value));
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: StudioConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
84
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: StudioConfigService, providedIn: 'root' });
|
|
85
|
+
}
|
|
86
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: StudioConfigService, decorators: [{
|
|
87
|
+
type: Injectable,
|
|
88
|
+
args: [{ providedIn: 'root' }]
|
|
89
|
+
}], ctorParameters: () => [] });
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Provide Studio configuration for the application
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* // app.config.ts
|
|
97
|
+
* import { provideStudioConfig } from '@eduboxpro/studio/config';
|
|
98
|
+
*
|
|
99
|
+
* export const appConfig: ApplicationConfig = {
|
|
100
|
+
* providers: [
|
|
101
|
+
* provideStudioConfig({
|
|
102
|
+
* theme: {
|
|
103
|
+
* mode: 'light',
|
|
104
|
+
* colors: {
|
|
105
|
+
* primary: '#3b82f6'
|
|
106
|
+
* }
|
|
107
|
+
* }
|
|
108
|
+
* })
|
|
109
|
+
* ]
|
|
110
|
+
* };
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
function provideStudioConfig(config = {}) {
|
|
114
|
+
return makeEnvironmentProviders([
|
|
115
|
+
{
|
|
116
|
+
provide: STUDIO_CONFIG,
|
|
117
|
+
useValue: config
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
provide: ENVIRONMENT_INITIALIZER,
|
|
121
|
+
multi: true,
|
|
122
|
+
useValue: () => {
|
|
123
|
+
const studioConfig = inject(StudioConfigService);
|
|
124
|
+
const initialConfig = inject(STUDIO_CONFIG);
|
|
125
|
+
studioConfig.configure(initialConfig);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
]);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Configuration module
|
|
133
|
+
* @module config
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
class ButtonComponent {
|
|
137
|
+
variant = input('solid', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
138
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
139
|
+
color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : []));
|
|
140
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
141
|
+
fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : []));
|
|
142
|
+
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
143
|
+
type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : []));
|
|
144
|
+
clicked = output();
|
|
145
|
+
hostClasses = computed(() => {
|
|
146
|
+
return [
|
|
147
|
+
'studio-button',
|
|
148
|
+
`studio-button--${this.variant()}`,
|
|
149
|
+
`studio-button--${this.size()}`,
|
|
150
|
+
`studio-button--${this.color()}`,
|
|
151
|
+
this.fullWidth() ? 'studio-button--full' : '',
|
|
152
|
+
this.loading() ? 'studio-button--loading' : ''
|
|
153
|
+
].filter(Boolean).join(' ');
|
|
154
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
|
|
155
|
+
handleClick(event) {
|
|
156
|
+
if (this.disabled() || this.loading()) {
|
|
157
|
+
event.preventDefault();
|
|
158
|
+
event.stopPropagation();
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
this.clicked.emit(event);
|
|
162
|
+
}
|
|
163
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
164
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.12", type: ButtonComponent, isStandalone: true, selector: "studio-button", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, host: { listeners: { "click": "handleClick($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() ? \"\" : null", "attr.type": "type()" } }, ngImport: i0, template: `
|
|
165
|
+
<span class="studio-button__content">
|
|
166
|
+
<ng-content />
|
|
167
|
+
</span>
|
|
168
|
+
`, isInline: true, styles: [":host{display:inline-block}.studio-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--studio-spacing-sm);font-family:var(--studio-font-family);font-weight:var(--studio-font-weight-medium);border:none;cursor:pointer;-webkit-user-select:none;user-select:none;position:relative;white-space:nowrap;vertical-align:middle;transition:background-color var(--studio-transition-fast),color var(--studio-transition-fast),border-color var(--studio-transition-fast),box-shadow var(--studio-transition-fast),transform var(--studio-transition-fast);border-radius:var(--studio-radius-md)}.studio-button:focus-visible{outline:2px solid var(--studio-primary);outline-offset:2px}.studio-button:active:not(:disabled):not(.studio-button--loading){transform:scale(.98)}.studio-button--sm{padding:var(--studio-spacing-xs) var(--studio-spacing-sm);font-size:var(--studio-font-size-sm);height:2rem;min-width:2rem}.studio-button--md{padding:var(--studio-spacing-sm) var(--studio-spacing-md);font-size:var(--studio-font-size-base);height:2.5rem;min-width:2.5rem}.studio-button--lg{padding:var(--studio-spacing-md) var(--studio-spacing-lg);font-size:var(--studio-font-size-lg);height:3rem;min-width:3rem}.studio-button--solid.studio-button--primary{background:var(--studio-primary);color:#fff}.studio-button--solid.studio-button--primary:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-primary-hover)}.studio-button--solid.studio-button--primary:active:not(:disabled):not(.studio-button--loading){background:var(--studio-primary-active)}.studio-button--outline.studio-button--primary{background:transparent;border:1px solid var(--studio-primary);color:var(--studio-primary)}.studio-button--outline.studio-button--primary:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-primary);color:#fff}.studio-button--ghost.studio-button--primary{background:transparent;color:var(--studio-primary)}.studio-button--ghost.studio-button--primary:hover:not(:disabled):not(.studio-button--loading){background:#3b82f61a}.studio-button--solid.studio-button--secondary{background:var(--studio-secondary);color:#fff}.studio-button--solid.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-secondary-hover)}.studio-button--solid.studio-button--secondary:active:not(:disabled):not(.studio-button--loading){background:var(--studio-secondary-active)}.studio-button--outline.studio-button--secondary{background:transparent;border:1px solid var(--studio-secondary);color:var(--studio-secondary)}.studio-button--outline.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-secondary);color:#fff}.studio-button--ghost.studio-button--secondary{background:transparent;color:var(--studio-secondary)}.studio-button--ghost.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading){background:#8b5cf61a}.studio-button--solid.studio-button--success{background:var(--studio-success);color:#fff}.studio-button--solid.studio-button--success:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-success-hover)}.studio-button--outline.studio-button--success{background:transparent;border:1px solid var(--studio-success);color:var(--studio-success)}.studio-button--outline.studio-button--success:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-success);color:#fff}.studio-button--ghost.studio-button--success{background:transparent;color:var(--studio-success)}.studio-button--ghost.studio-button--success:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-success-bg)}.studio-button--solid.studio-button--error{background:var(--studio-error);color:#fff}.studio-button--solid.studio-button--error:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-error-hover)}.studio-button--outline.studio-button--error{background:transparent;border:1px solid var(--studio-error);color:var(--studio-error)}.studio-button--outline.studio-button--error:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-error);color:#fff}.studio-button--ghost.studio-button--error{background:transparent;color:var(--studio-error)}.studio-button--ghost.studio-button--error:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-error-bg)}.studio-button--solid.studio-button--warning{background:var(--studio-warning);color:#fff}.studio-button--solid.studio-button--warning:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-warning-hover)}.studio-button--outline.studio-button--warning{background:transparent;border:1px solid var(--studio-warning);color:var(--studio-warning)}.studio-button--outline.studio-button--warning:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-warning);color:#fff}.studio-button--ghost.studio-button--warning{background:transparent;color:var(--studio-warning)}.studio-button--ghost.studio-button--warning:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-warning-bg)}.studio-button--full{width:100%}.studio-button--loading{cursor:wait;opacity:.7}.studio-button:disabled{opacity:.5;cursor:not-allowed}.studio-button__content{display:inline-flex;align-items:center;gap:var(--studio-spacing-sm)}[data-theme=dark] .studio-button--solid.studio-button--primary,[data-theme=dark] .studio-button--solid.studio-button--secondary,[data-theme=dark] .studio-button--solid.studio-button--success,[data-theme=dark] .studio-button--solid.studio-button--error,[data-theme=dark] .studio-button--solid.studio-button--warning{box-shadow:var(--studio-shadow-sm)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
169
|
+
}
|
|
170
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ButtonComponent, decorators: [{
|
|
171
|
+
type: Component,
|
|
172
|
+
args: [{ selector: 'studio-button', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
173
|
+
'[class]': 'hostClasses()',
|
|
174
|
+
'[attr.disabled]': 'disabled() ? "" : null',
|
|
175
|
+
'[attr.type]': 'type()',
|
|
176
|
+
'(click)': 'handleClick($event)'
|
|
177
|
+
}, template: `
|
|
178
|
+
<span class="studio-button__content">
|
|
179
|
+
<ng-content />
|
|
180
|
+
</span>
|
|
181
|
+
`, styles: [":host{display:inline-block}.studio-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--studio-spacing-sm);font-family:var(--studio-font-family);font-weight:var(--studio-font-weight-medium);border:none;cursor:pointer;-webkit-user-select:none;user-select:none;position:relative;white-space:nowrap;vertical-align:middle;transition:background-color var(--studio-transition-fast),color var(--studio-transition-fast),border-color var(--studio-transition-fast),box-shadow var(--studio-transition-fast),transform var(--studio-transition-fast);border-radius:var(--studio-radius-md)}.studio-button:focus-visible{outline:2px solid var(--studio-primary);outline-offset:2px}.studio-button:active:not(:disabled):not(.studio-button--loading){transform:scale(.98)}.studio-button--sm{padding:var(--studio-spacing-xs) var(--studio-spacing-sm);font-size:var(--studio-font-size-sm);height:2rem;min-width:2rem}.studio-button--md{padding:var(--studio-spacing-sm) var(--studio-spacing-md);font-size:var(--studio-font-size-base);height:2.5rem;min-width:2.5rem}.studio-button--lg{padding:var(--studio-spacing-md) var(--studio-spacing-lg);font-size:var(--studio-font-size-lg);height:3rem;min-width:3rem}.studio-button--solid.studio-button--primary{background:var(--studio-primary);color:#fff}.studio-button--solid.studio-button--primary:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-primary-hover)}.studio-button--solid.studio-button--primary:active:not(:disabled):not(.studio-button--loading){background:var(--studio-primary-active)}.studio-button--outline.studio-button--primary{background:transparent;border:1px solid var(--studio-primary);color:var(--studio-primary)}.studio-button--outline.studio-button--primary:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-primary);color:#fff}.studio-button--ghost.studio-button--primary{background:transparent;color:var(--studio-primary)}.studio-button--ghost.studio-button--primary:hover:not(:disabled):not(.studio-button--loading){background:#3b82f61a}.studio-button--solid.studio-button--secondary{background:var(--studio-secondary);color:#fff}.studio-button--solid.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-secondary-hover)}.studio-button--solid.studio-button--secondary:active:not(:disabled):not(.studio-button--loading){background:var(--studio-secondary-active)}.studio-button--outline.studio-button--secondary{background:transparent;border:1px solid var(--studio-secondary);color:var(--studio-secondary)}.studio-button--outline.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-secondary);color:#fff}.studio-button--ghost.studio-button--secondary{background:transparent;color:var(--studio-secondary)}.studio-button--ghost.studio-button--secondary:hover:not(:disabled):not(.studio-button--loading){background:#8b5cf61a}.studio-button--solid.studio-button--success{background:var(--studio-success);color:#fff}.studio-button--solid.studio-button--success:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-success-hover)}.studio-button--outline.studio-button--success{background:transparent;border:1px solid var(--studio-success);color:var(--studio-success)}.studio-button--outline.studio-button--success:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-success);color:#fff}.studio-button--ghost.studio-button--success{background:transparent;color:var(--studio-success)}.studio-button--ghost.studio-button--success:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-success-bg)}.studio-button--solid.studio-button--error{background:var(--studio-error);color:#fff}.studio-button--solid.studio-button--error:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-error-hover)}.studio-button--outline.studio-button--error{background:transparent;border:1px solid var(--studio-error);color:var(--studio-error)}.studio-button--outline.studio-button--error:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-error);color:#fff}.studio-button--ghost.studio-button--error{background:transparent;color:var(--studio-error)}.studio-button--ghost.studio-button--error:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-error-bg)}.studio-button--solid.studio-button--warning{background:var(--studio-warning);color:#fff}.studio-button--solid.studio-button--warning:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-warning-hover)}.studio-button--outline.studio-button--warning{background:transparent;border:1px solid var(--studio-warning);color:var(--studio-warning)}.studio-button--outline.studio-button--warning:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-warning);color:#fff}.studio-button--ghost.studio-button--warning{background:transparent;color:var(--studio-warning)}.studio-button--ghost.studio-button--warning:hover:not(:disabled):not(.studio-button--loading){background:var(--studio-warning-bg)}.studio-button--full{width:100%}.studio-button--loading{cursor:wait;opacity:.7}.studio-button:disabled{opacity:.5;cursor:not-allowed}.studio-button__content{display:inline-flex;align-items:center;gap:var(--studio-spacing-sm)}[data-theme=dark] .studio-button--solid.studio-button--primary,[data-theme=dark] .studio-button--solid.studio-button--secondary,[data-theme=dark] .studio-button--solid.studio-button--success,[data-theme=dark] .studio-button--solid.studio-button--error,[data-theme=dark] .studio-button--solid.studio-button--warning{box-shadow:var(--studio-shadow-sm)}\n"] }]
|
|
182
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Button component
|
|
186
|
+
*/
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Primitives (Atoms)
|
|
190
|
+
* Basic building blocks
|
|
191
|
+
*/
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Composites (Molecules + Organisms)
|
|
195
|
+
* Complex components built from primitives
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Education components
|
|
200
|
+
* Domain-specific components for educational platforms
|
|
201
|
+
*/
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Utilities
|
|
205
|
+
* Helper functions, directives, pipes
|
|
206
|
+
*/
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Public API Surface of @eduboxpro/studio
|
|
210
|
+
*/
|
|
211
|
+
/* ========================================
|
|
212
|
+
* Configuration
|
|
213
|
+
* ======================================== */
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Generated bundle index. Do not edit.
|
|
217
|
+
*/
|
|
218
|
+
|
|
219
|
+
export { ButtonComponent, STUDIO_CONFIG, StudioConfigService, provideStudioConfig };
|
|
220
|
+
//# sourceMappingURL=eduboxpro-studio.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eduboxpro-studio.mjs","sources":["../../../projects/studio/src/lib/config/studio.config.ts","../../../projects/studio/src/lib/config/studio.service.ts","../../../projects/studio/src/lib/config/provide-studio.ts","../../../projects/studio/src/lib/config/index.ts","../../../projects/studio/src/lib/primitives/button/button.component.ts","../../../projects/studio/src/lib/primitives/button/index.ts","../../../projects/studio/src/lib/primitives/index.ts","../../../projects/studio/src/lib/composites/index.ts","../../../projects/studio/src/lib/education/index.ts","../../../projects/studio/src/lib/utils/index.ts","../../../projects/studio/src/public-api.ts","../../../projects/studio/src/eduboxpro-studio.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n/**\n * Theme mode: light or dark\n */\nexport type ThemeMode = 'light' | 'dark';\n\n/**\n * Theme configuration interface\n */\nexport interface StudioThemeConfig {\n /**\n * Theme mode (default: 'light')\n */\n mode?: ThemeMode;\n\n /**\n * Color tokens override\n */\n colors?: {\n primary?: string;\n secondary?: string;\n success?: string;\n error?: string;\n warning?: string;\n info?: string;\n };\n\n /**\n * Typography tokens override\n */\n typography?: {\n fontFamily?: string;\n fontSize?: {\n xs?: string;\n sm?: string;\n base?: string;\n lg?: string;\n xl?: string;\n '2xl'?: string;\n };\n fontWeight?: {\n normal?: number;\n medium?: number;\n semibold?: number;\n bold?: number;\n };\n };\n\n /**\n * Spacing tokens override\n */\n spacing?: {\n xs?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n '2xl'?: string;\n };\n\n /**\n * Border radius tokens override\n */\n borderRadius?: {\n none?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n full?: string;\n };\n\n /**\n * Shadow tokens override\n */\n shadows?: {\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n };\n}\n\n/**\n * Main Studio configuration interface\n */\nexport interface StudioConfig {\n /**\n * Theme configuration\n */\n theme?: StudioThemeConfig;\n}\n\n/**\n * Injection token for Studio configuration\n */\nexport const STUDIO_CONFIG = new InjectionToken<StudioConfig>('STUDIO_CONFIG', {\n providedIn: 'root',\n factory: () => ({})\n});\n","import { Injectable, inject, signal, effect } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\nimport { StudioConfig, StudioThemeConfig, ThemeMode } from './studio.config';\n\n@Injectable({ providedIn: 'root' })\nexport class StudioConfigService {\n private readonly document = inject(DOCUMENT);\n\n readonly config = signal<StudioConfig>({});\n readonly themeMode = signal<ThemeMode>('light');\n\n constructor() {\n effect(() => {\n this.applyTheme(this.config().theme);\n }, { allowSignalWrites: false });\n }\n\n configure(config: StudioConfig): void {\n this.config.set(config);\n if (config.theme?.mode) {\n this.setThemeMode(config.theme.mode);\n }\n }\n\n setThemeMode(mode: ThemeMode): void {\n this.themeMode.set(mode);\n this.document.documentElement.setAttribute('data-theme', mode);\n }\n\n toggleTheme(): void {\n const newMode = this.themeMode() === 'light' ? 'dark' : 'light';\n this.setThemeMode(newMode);\n }\n\n async loadFromBackend(organizationSlug: string): Promise<void> {\n try {\n const response = await fetch(`/api/organizations/${organizationSlug}/design-config`);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const config = await response.json();\n this.configure(config);\n } catch (error) {\n console.error('[Studio] Failed to load config from backend:', error);\n throw error;\n }\n }\n\n private applyTheme(theme?: StudioThemeConfig): void {\n if (!theme) return;\n\n const root = this.document.documentElement;\n\n if (theme.colors) {\n this.applyTokens(root, 'studio', theme.colors);\n }\n if (theme.spacing) {\n this.applyTokens(root, 'studio-spacing', theme.spacing);\n }\n if (theme.borderRadius) {\n this.applyTokens(root, 'studio-radius', theme.borderRadius);\n }\n if (theme.shadows) {\n this.applyTokens(root, 'studio-shadow', theme.shadows);\n }\n if (theme.typography?.fontFamily) {\n root.style.setProperty('--studio-font-family', theme.typography.fontFamily);\n }\n if (theme.typography?.fontSize) {\n this.applyTokens(root, 'studio-font-size', theme.typography.fontSize);\n }\n if (theme.typography?.fontWeight) {\n this.applyTokens(root, 'studio-font-weight', theme.typography.fontWeight);\n }\n }\n\n private applyTokens(\n root: HTMLElement,\n prefix: string,\n tokens: Record<string, string | number>\n ): void {\n Object.entries(tokens).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n root.style.setProperty(`--${prefix}-${key}`, String(value));\n }\n });\n }\n}\n","import { EnvironmentProviders, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, inject } from '@angular/core';\nimport { STUDIO_CONFIG, StudioConfig } from './studio.config';\nimport { StudioConfigService } from './studio.service';\n\n/**\n * Provide Studio configuration for the application\n *\n * @example\n * ```typescript\n * // app.config.ts\n * import { provideStudioConfig } from '@eduboxpro/studio/config';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideStudioConfig({\n * theme: {\n * mode: 'light',\n * colors: {\n * primary: '#3b82f6'\n * }\n * }\n * })\n * ]\n * };\n * ```\n */\nexport function provideStudioConfig(config: StudioConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: STUDIO_CONFIG,\n useValue: config\n },\n {\n provide: ENVIRONMENT_INITIALIZER,\n multi: true,\n useValue: () => {\n const studioConfig = inject(StudioConfigService);\n const initialConfig = inject(STUDIO_CONFIG);\n studioConfig.configure(initialConfig);\n }\n }\n ]);\n}\n","/**\n * Configuration module\n * @module config\n */\n\nexport * from './studio.config';\nexport * from './studio.service';\nexport * from './provide-studio';\n","import { Component, input, output, computed, ChangeDetectionStrategy } from '@angular/core';\n\n@Component({\n selector: 'studio-button',\n standalone: true,\n imports: [],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n '[attr.disabled]': 'disabled() ? \"\" : null',\n '[attr.type]': 'type()',\n '(click)': 'handleClick($event)'\n },\n template: `\n <span class=\"studio-button__content\">\n <ng-content />\n </span>\n `,\n styleUrl: './button.component.scss'\n})\nexport class ButtonComponent {\n variant = input<'solid' | 'outline' | 'ghost'>('solid');\n size = input<'sm' | 'md' | 'lg'>('md');\n color = input<'primary' | 'secondary' | 'success' | 'error' | 'warning'>('primary');\n disabled = input<boolean>(false);\n fullWidth = input<boolean>(false);\n loading = input<boolean>(false);\n type = input<'button' | 'submit' | 'reset'>('button');\n\n clicked = output<MouseEvent>();\n\n protected hostClasses = computed(() => {\n return [\n 'studio-button',\n `studio-button--${this.variant()}`,\n `studio-button--${this.size()}`,\n `studio-button--${this.color()}`,\n this.fullWidth() ? 'studio-button--full' : '',\n this.loading() ? 'studio-button--loading' : ''\n ].filter(Boolean).join(' ');\n });\n\n protected handleClick(event: MouseEvent): void {\n if (this.disabled() || this.loading()) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n this.clicked.emit(event);\n }\n}\n","/**\n * Button component\n */\n\nexport * from './button.component';\n","/**\n * Primitives (Atoms)\n * Basic building blocks\n */\n\nexport * from './button';\n","/**\n * Composites (Molecules + Organisms)\n * Complex components built from primitives\n */\n\n// Export composite components here\n// Example: export * from './form-field';\n\n// Empty export to make this a valid module\nexport {};\n","/**\n * Education components\n * Domain-specific components for educational platforms\n */\n\n// Export education components here\n// Example: export * from './course-card';\n// Example: export * from './lesson-viewer';\n// Example: export * from './quiz-builder';\n\n// Empty export to make this a valid module\nexport {};\n","/**\n * Utilities\n * Helper functions, directives, pipes\n */\n\n// Export utilities here\n// Example: export * from './format-date.pipe';\n// Example: export * from './auto-focus.directive';\n\n// Empty export to make this a valid module\nexport {};\n","/**\n * Public API Surface of @eduboxpro/studio\n */\n\n/* ========================================\n * Configuration\n * ======================================== */\nexport * from './lib/config';\n\n/* ========================================\n * Components\n * ======================================== */\nexport * from './lib/primitives';\nexport * from './lib/composites';\nexport * from './lib/education';\n\n/* ========================================\n * Utilities\n * ======================================== */\nexport * from './lib/utils';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { InjectionToken, EnvironmentProviders } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Theme mode: light or dark
|
|
6
|
+
*/
|
|
7
|
+
type ThemeMode = 'light' | 'dark';
|
|
8
|
+
/**
|
|
9
|
+
* Theme configuration interface
|
|
10
|
+
*/
|
|
11
|
+
interface StudioThemeConfig {
|
|
12
|
+
/**
|
|
13
|
+
* Theme mode (default: 'light')
|
|
14
|
+
*/
|
|
15
|
+
mode?: ThemeMode;
|
|
16
|
+
/**
|
|
17
|
+
* Color tokens override
|
|
18
|
+
*/
|
|
19
|
+
colors?: {
|
|
20
|
+
primary?: string;
|
|
21
|
+
secondary?: string;
|
|
22
|
+
success?: string;
|
|
23
|
+
error?: string;
|
|
24
|
+
warning?: string;
|
|
25
|
+
info?: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Typography tokens override
|
|
29
|
+
*/
|
|
30
|
+
typography?: {
|
|
31
|
+
fontFamily?: string;
|
|
32
|
+
fontSize?: {
|
|
33
|
+
xs?: string;
|
|
34
|
+
sm?: string;
|
|
35
|
+
base?: string;
|
|
36
|
+
lg?: string;
|
|
37
|
+
xl?: string;
|
|
38
|
+
'2xl'?: string;
|
|
39
|
+
};
|
|
40
|
+
fontWeight?: {
|
|
41
|
+
normal?: number;
|
|
42
|
+
medium?: number;
|
|
43
|
+
semibold?: number;
|
|
44
|
+
bold?: number;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Spacing tokens override
|
|
49
|
+
*/
|
|
50
|
+
spacing?: {
|
|
51
|
+
xs?: string;
|
|
52
|
+
sm?: string;
|
|
53
|
+
md?: string;
|
|
54
|
+
lg?: string;
|
|
55
|
+
xl?: string;
|
|
56
|
+
'2xl'?: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Border radius tokens override
|
|
60
|
+
*/
|
|
61
|
+
borderRadius?: {
|
|
62
|
+
none?: string;
|
|
63
|
+
sm?: string;
|
|
64
|
+
md?: string;
|
|
65
|
+
lg?: string;
|
|
66
|
+
xl?: string;
|
|
67
|
+
full?: string;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Shadow tokens override
|
|
71
|
+
*/
|
|
72
|
+
shadows?: {
|
|
73
|
+
sm?: string;
|
|
74
|
+
md?: string;
|
|
75
|
+
lg?: string;
|
|
76
|
+
xl?: string;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Main Studio configuration interface
|
|
81
|
+
*/
|
|
82
|
+
interface StudioConfig {
|
|
83
|
+
/**
|
|
84
|
+
* Theme configuration
|
|
85
|
+
*/
|
|
86
|
+
theme?: StudioThemeConfig;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Injection token for Studio configuration
|
|
90
|
+
*/
|
|
91
|
+
declare const STUDIO_CONFIG: InjectionToken<StudioConfig>;
|
|
92
|
+
|
|
93
|
+
declare class StudioConfigService {
|
|
94
|
+
private readonly document;
|
|
95
|
+
readonly config: _angular_core.WritableSignal<StudioConfig>;
|
|
96
|
+
readonly themeMode: _angular_core.WritableSignal<ThemeMode>;
|
|
97
|
+
constructor();
|
|
98
|
+
configure(config: StudioConfig): void;
|
|
99
|
+
setThemeMode(mode: ThemeMode): void;
|
|
100
|
+
toggleTheme(): void;
|
|
101
|
+
loadFromBackend(organizationSlug: string): Promise<void>;
|
|
102
|
+
private applyTheme;
|
|
103
|
+
private applyTokens;
|
|
104
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<StudioConfigService, never>;
|
|
105
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<StudioConfigService>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Provide Studio configuration for the application
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* // app.config.ts
|
|
114
|
+
* import { provideStudioConfig } from '@eduboxpro/studio/config';
|
|
115
|
+
*
|
|
116
|
+
* export const appConfig: ApplicationConfig = {
|
|
117
|
+
* providers: [
|
|
118
|
+
* provideStudioConfig({
|
|
119
|
+
* theme: {
|
|
120
|
+
* mode: 'light',
|
|
121
|
+
* colors: {
|
|
122
|
+
* primary: '#3b82f6'
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
* })
|
|
126
|
+
* ]
|
|
127
|
+
* };
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
declare function provideStudioConfig(config?: StudioConfig): EnvironmentProviders;
|
|
131
|
+
|
|
132
|
+
declare class ButtonComponent {
|
|
133
|
+
variant: _angular_core.InputSignal<"solid" | "outline" | "ghost">;
|
|
134
|
+
size: _angular_core.InputSignal<"sm" | "md" | "lg">;
|
|
135
|
+
color: _angular_core.InputSignal<"primary" | "secondary" | "success" | "error" | "warning">;
|
|
136
|
+
disabled: _angular_core.InputSignal<boolean>;
|
|
137
|
+
fullWidth: _angular_core.InputSignal<boolean>;
|
|
138
|
+
loading: _angular_core.InputSignal<boolean>;
|
|
139
|
+
type: _angular_core.InputSignal<"button" | "submit" | "reset">;
|
|
140
|
+
clicked: _angular_core.OutputEmitterRef<MouseEvent>;
|
|
141
|
+
protected hostClasses: _angular_core.Signal<string>;
|
|
142
|
+
protected handleClick(event: MouseEvent): void;
|
|
143
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ButtonComponent, never>;
|
|
144
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ButtonComponent, "studio-button", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "fullWidth": { "alias": "fullWidth"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; }, { "clicked": "clicked"; }, never, ["*"], true, never>;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export { ButtonComponent, STUDIO_CONFIG, StudioConfigService, provideStudioConfig };
|
|
148
|
+
export type { StudioConfig, StudioThemeConfig, ThemeMode };
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@eduboxpro/studio",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Modern Angular UI library for educational platforms with customizable design system",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"angular",
|
|
7
|
+
"ui",
|
|
8
|
+
"components",
|
|
9
|
+
"design-system",
|
|
10
|
+
"education",
|
|
11
|
+
"edubox",
|
|
12
|
+
"standalone",
|
|
13
|
+
"signals"
|
|
14
|
+
],
|
|
15
|
+
"author": "EduBoxPro Team",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/eduboxpro/studio"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@angular/common": "^20.3.0",
|
|
23
|
+
"@angular/core": "^20.3.0"
|
|
24
|
+
},
|
|
25
|
+
"sideEffects": [
|
|
26
|
+
"*.css",
|
|
27
|
+
"*.scss"
|
|
28
|
+
],
|
|
29
|
+
"module": "fesm2022/eduboxpro-studio.mjs",
|
|
30
|
+
"typings": "index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
"./package.json": {
|
|
33
|
+
"default": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./index.d.ts",
|
|
37
|
+
"default": "./fesm2022/eduboxpro-studio.mjs"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"tslib": "^2.3.0"
|
|
42
|
+
}
|
|
43
|
+
}
|