tailjng 0.0.62 → 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/README.md +186 -32
- package/cli/component-manager.js +71 -20
- package/cli/execute/init-app.js +251 -0
- package/cli/file-operations.js +45 -29
- package/cli/index.js +66 -15
- package/cli/settings/components-list.js +4 -151
- package/cli/settings/header-generator.js +9 -10
- package/cli/settings/lib-utils.js +89 -0
- package/cli/settings/overwrite-policy.js +18 -0
- package/cli/settings/path-utils.js +14 -29
- package/cli/settings/project-utils.js +220 -0
- package/cli/settings/prompt-utils.js +66 -5
- package/cli/templates/app.generator.js +382 -0
- package/fesm2022/tailjng.mjs +232 -66
- package/fesm2022/tailjng.mjs.map +1 -1
- package/lib/services/static/colors.service.d.ts +17 -0
- package/lib/services/transformer/transform.service.d.ts +3 -3
- package/package.json +1 -1
- package/public-api.d.ts +2 -0
- package/registry/components.json +164 -0
- package/src/lib/components/alert/alert-dialog/dialog-alert.component.css +17 -0
- package/src/lib/components/alert/alert-dialog/dialog-alert.component.html +83 -51
- package/src/lib/components/alert/alert-dialog/dialog-alert.component.ts +85 -53
- package/src/lib/components/alert/alert-toast/toast-alert.component.css +38 -4
- package/src/lib/components/alert/alert-toast/toast-alert.component.html +72 -40
- package/src/lib/components/alert/alert-toast/toast-alert.component.ts +84 -19
- package/src/lib/components/badge/badge.component.ts +1 -2
- package/src/lib/components/button/button.component.css +14 -0
- package/src/lib/components/button/button.component.html +17 -17
- package/src/lib/components/button/button.component.ts +139 -48
- package/src/lib/components/card/card-crud-complete/complete-crud-card.component.ts +5 -1
- package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.html +1 -1
- package/src/lib/components/filter/filter-complete/complete-filter.component.html +1 -1
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.html +8 -5
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.scss +12 -0
- package/src/lib/components/select/select-dropdown/dropdown-select.component.css +4 -0
- package/src/lib/components/select/select-dropdown/dropdown-select.component.html +1 -1
- package/src/lib/components/select/select-dropdown/dropdown-select.component.ts +3 -3
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.css +4 -0
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.html +1 -1
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.ts +30 -20
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.html +504 -170
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.scss +92 -0
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.ts +139 -5
- package/src/lib/components/table/table-crud-complete/expand-grid/table-expand-grid.builder.ts +116 -0
- package/src/lib/components/table/table-crud-complete/expand-grid/table-expand-grid.helper.ts +43 -0
- package/src/lib/components/table/table-crud-complete/expand-grid/table-expand-grid.types.ts +39 -0
- package/src/lib/components/table/table-crud-complete/index.ts +3 -0
- package/src/lib/components/toggle-radio/toggle-radio.component.css +4 -0
- package/src/lib/components/toggle-radio/toggle-radio.component.html +4 -4
- package/src/lib/components/toggle-radio/toggle-radio.component.ts +15 -6
- package/src/lib/components/tooltip/tooltip.service.ts +0 -30
- package/tailjng-0.1.0.tgz +0 -0
- package/src/lib/components/color/colors.service.ts +0 -187
package/cli/file-operations.js
CHANGED
|
@@ -7,10 +7,50 @@ const { generateHeaderComment } = require("./settings/header-generator")
|
|
|
7
7
|
const { askOverwrite } = require("./settings/prompt-utils")
|
|
8
8
|
const { buildTargetPath, parseComponentPath } = require("./settings/path-utils")
|
|
9
9
|
|
|
10
|
+
const TEXT_EXTENSIONS = new Set([".ts", ".js", ".html", ".css", ".scss", ".json", ".md"])
|
|
11
|
+
|
|
12
|
+
function shouldAddHeader(fileName) {
|
|
13
|
+
return TEXT_EXTENSIONS.has(path.extname(fileName).toLowerCase())
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function copyFileWithHeader(srcFile, destFile) {
|
|
17
|
+
fs.mkdirSync(path.dirname(destFile), { recursive: true })
|
|
18
|
+
|
|
19
|
+
if (!shouldAddHeader(path.basename(srcFile))) {
|
|
20
|
+
fs.copyFileSync(srcFile, destFile)
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let content = fs.readFileSync(srcFile, "utf8")
|
|
25
|
+
const headerComment = generateHeaderComment(path.basename(srcFile))
|
|
26
|
+
content = headerComment + "\n\n" + content
|
|
27
|
+
fs.writeFileSync(destFile, content)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function copyDirectoryRecursive(srcDir, destDir, projectRoot) {
|
|
31
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true })
|
|
32
|
+
|
|
33
|
+
for (const entry of entries) {
|
|
34
|
+
const srcPath = path.join(srcDir, entry.name)
|
|
35
|
+
const destPath = path.join(destDir, entry.name)
|
|
36
|
+
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
copyDirectoryRecursive(srcPath, destPath, projectRoot)
|
|
39
|
+
continue
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!entry.isFile()) continue
|
|
43
|
+
|
|
44
|
+
copyFileWithHeader(srcPath, destPath)
|
|
45
|
+
const relativePath = path.relative(projectRoot, destPath)
|
|
46
|
+
console.log(
|
|
47
|
+
`${COLORS.green}${COLORS.bright}[tailjng CLI]${COLORS.reset} ${COLORS.green}Copied file: ${COLORS.bright}${relativePath}${COLORS.reset}`,
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
10
52
|
async function copyComponentFiles(componentName, componentPath, isDependency = false) {
|
|
11
|
-
// Detect the root directory where node_modules is located
|
|
12
53
|
let currentDir = process.cwd()
|
|
13
|
-
// Up to the root directory where node_modules is located
|
|
14
54
|
while (!fs.existsSync(path.join(currentDir, "node_modules"))) {
|
|
15
55
|
currentDir = path.dirname(currentDir)
|
|
16
56
|
if (currentDir === path.dirname(currentDir)) {
|
|
@@ -19,15 +59,11 @@ async function copyComponentFiles(componentName, componentPath, isDependency = f
|
|
|
19
59
|
}
|
|
20
60
|
}
|
|
21
61
|
|
|
22
|
-
// Now currentDir points to the root directory where node_modules is located
|
|
23
62
|
const nodeModulesPath = path.join(currentDir, "node_modules", "tailjng", componentPath)
|
|
24
63
|
const projectRoot = process.cwd()
|
|
25
|
-
|
|
26
|
-
// Use the new function to build the target path while maintaining the folder structure
|
|
27
64
|
const targetPath = buildTargetPath(projectRoot, componentName, componentPath)
|
|
28
65
|
const pathInfo = parseComponentPath(componentPath)
|
|
29
66
|
|
|
30
|
-
// Check if the component exists in the correct path
|
|
31
67
|
if (!fs.existsSync(nodeModulesPath)) {
|
|
32
68
|
console.error(
|
|
33
69
|
`${COLORS.red}${COLORS.bright}[tailjng CLI]${COLORS.reset} ${COLORS.red}ERROR: Component path ${COLORS.bright}"${nodeModulesPath}"${COLORS.reset} ${COLORS.red}does not exist.${COLORS.reset}`,
|
|
@@ -35,17 +71,15 @@ async function copyComponentFiles(componentName, componentPath, isDependency = f
|
|
|
35
71
|
process.exit(1)
|
|
36
72
|
}
|
|
37
73
|
|
|
38
|
-
// Check if the target path already exists
|
|
39
74
|
if (fs.existsSync(targetPath)) {
|
|
40
75
|
const relativeTargetPath = path.relative(projectRoot, targetPath)
|
|
41
76
|
const shouldOverwrite = await askOverwrite(componentName, relativeTargetPath, isDependency)
|
|
42
77
|
|
|
43
78
|
if (!shouldOverwrite) {
|
|
44
79
|
console.log(`${COLORS.dim}${COLORS.bright}[tailjng CLI]${COLORS.reset} ${COLORS.dim}Skipping ${COLORS.bright}"${componentName}"${COLORS.reset} ${COLORS.dim}- keeping existing version.${COLORS.reset}`)
|
|
45
|
-
return false
|
|
80
|
+
return false
|
|
46
81
|
}
|
|
47
82
|
|
|
48
|
-
// If decided to overwrite, remove the existing directory
|
|
49
83
|
console.log(`${COLORS.yellow}${COLORS.bright}[tailjng CLI]${COLORS.reset} ${COLORS.yellow}Removing existing ${COLORS.bright}"${componentName}"${COLORS.reset} ${COLORS.yellow}to overwrite...${COLORS.reset}`)
|
|
50
84
|
fs.rmSync(targetPath, { recursive: true, force: true })
|
|
51
85
|
}
|
|
@@ -53,7 +87,6 @@ async function copyComponentFiles(componentName, componentPath, isDependency = f
|
|
|
53
87
|
const componentType = isDependency ? "dependency component" : "component"
|
|
54
88
|
const relativeTargetPath = path.relative(projectRoot, targetPath)
|
|
55
89
|
|
|
56
|
-
// See if the component has subfolders
|
|
57
90
|
if (pathInfo.hasSubfolders) {
|
|
58
91
|
console.log(
|
|
59
92
|
`${COLORS.blue}${COLORS.bright}[tailjng CLI]${COLORS.reset} ${COLORS.blue}Copying ${componentType} ${COLORS.bright}"${componentName}"${COLORS.reset} (${pathInfo.fullSubPath}) → ${relativeTargetPath}${COLORS.reset}`,
|
|
@@ -64,27 +97,10 @@ async function copyComponentFiles(componentName, componentPath, isDependency = f
|
|
|
64
97
|
)
|
|
65
98
|
}
|
|
66
99
|
|
|
67
|
-
// Create the target directory structure
|
|
68
100
|
fs.mkdirSync(targetPath, { recursive: true })
|
|
101
|
+
copyDirectoryRecursive(nodeModulesPath, targetPath, projectRoot)
|
|
69
102
|
|
|
70
|
-
|
|
71
|
-
files.forEach((file) => {
|
|
72
|
-
const srcFile = path.join(nodeModulesPath, file)
|
|
73
|
-
const destFile = path.join(targetPath, file)
|
|
74
|
-
let content = fs.readFileSync(srcFile, "utf8")
|
|
75
|
-
|
|
76
|
-
// Add header comment to the content
|
|
77
|
-
const headerComment = generateHeaderComment(file)
|
|
78
|
-
content = headerComment + "\n\n" + content
|
|
79
|
-
|
|
80
|
-
// Here you can add more processing logic if needed
|
|
81
|
-
// For example, replace imports, etc.
|
|
82
|
-
|
|
83
|
-
fs.writeFileSync(destFile, content)
|
|
84
|
-
console.log(`${COLORS.green}${COLORS.bright}[tailjng CLI]${COLORS.reset} ${COLORS.green}Copied file: ${COLORS.bright}${file}${COLORS.reset}`)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
return true // Return true to indicate that it was installed successfully
|
|
103
|
+
return true
|
|
88
104
|
}
|
|
89
105
|
|
|
90
106
|
module.exports = { copyComponentFiles }
|
package/cli/index.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// index.js
|
|
3
|
+
// index.js — tailjng CLI entry point
|
|
4
|
+
|
|
4
5
|
const { checkTailwindInstalled } = require("./settings/tailwind-check")
|
|
5
6
|
const { addComponent, installAllComponents } = require("./component-manager")
|
|
6
7
|
const { getComponentList } = require("./settings/components-list")
|
|
8
|
+
const { getPackageVersion } = require("./settings/lib-utils")
|
|
9
|
+
const { isComponentInstalled } = require("./settings/path-utils")
|
|
7
10
|
const { COLORS } = require("./settings/colors")
|
|
8
11
|
|
|
9
12
|
const args = process.argv.slice(2)
|
|
10
13
|
const command = args[0]
|
|
11
14
|
|
|
12
15
|
async function main() {
|
|
16
|
+
if (command === "init:app") {
|
|
17
|
+
require("./execute/init-app")
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
13
21
|
if (command === "add") {
|
|
14
22
|
const componentName = args[1]
|
|
15
23
|
if (!componentName) {
|
|
@@ -19,37 +27,80 @@ async function main() {
|
|
|
19
27
|
}
|
|
20
28
|
checkTailwindInstalled()
|
|
21
29
|
await addComponent(componentName, getComponentList())
|
|
22
|
-
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (command === "list") {
|
|
23
34
|
showComponentList()
|
|
24
|
-
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (command === "install-all") {
|
|
25
39
|
checkTailwindInstalled()
|
|
26
40
|
await installAllComponents(getComponentList())
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (command === "version") {
|
|
45
|
+
console.log(`${COLORS.cyan}tailjng${COLORS.reset} v${getPackageVersion(__dirname)}`)
|
|
46
|
+
return
|
|
32
47
|
}
|
|
48
|
+
|
|
49
|
+
showHelp()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function showHelp() {
|
|
53
|
+
console.log(`${COLORS.bright}${COLORS.blue}tailjng CLI${COLORS.reset} v${getPackageVersion(__dirname)}
|
|
54
|
+
|
|
55
|
+
${COLORS.bright}Project setup${COLORS.reset}
|
|
56
|
+
${COLORS.cyan}npx tailjng init:app${COLORS.reset} Configure Tailwind, providers, styles (no UI)
|
|
57
|
+
${COLORS.cyan}npx tailjng init:app --with-components${COLORS.reset} init:app + mode-toggle and alerts
|
|
58
|
+
|
|
59
|
+
${COLORS.bright}Components${COLORS.reset} ${COLORS.dim}(run from your Angular app directory)${COLORS.reset}
|
|
60
|
+
${COLORS.cyan}npx tailjng add${COLORS.reset} ${COLORS.dim}<name>${COLORS.reset} Install one component + dependencies
|
|
61
|
+
${COLORS.cyan}npx tailjng install-all${COLORS.reset} Install all registry components
|
|
62
|
+
${COLORS.cyan}npx tailjng list${COLORS.reset} List available components
|
|
63
|
+
|
|
64
|
+
${COLORS.bright}Info${COLORS.reset}
|
|
65
|
+
${COLORS.cyan}npx tailjng version${COLORS.reset} Show installed package version`)
|
|
33
66
|
}
|
|
34
67
|
|
|
35
68
|
function showComponentList() {
|
|
36
69
|
const componentList = getComponentList()
|
|
37
|
-
|
|
70
|
+
const names = Object.keys(componentList).sort()
|
|
71
|
+
const projectRoot = process.cwd()
|
|
72
|
+
|
|
73
|
+
if (names.length === 0) {
|
|
38
74
|
console.log(`${COLORS.yellow}[tailjng CLI] No components available.${COLORS.reset}`)
|
|
39
75
|
return
|
|
40
76
|
}
|
|
41
77
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
78
|
+
let installedCount = 0
|
|
79
|
+
|
|
80
|
+
console.log(`${COLORS.cyan}[tailjng CLI] Available components (${names.length}):${COLORS.reset}`)
|
|
81
|
+
console.log(`${COLORS.dim}Use: npx tailjng add <name>${COLORS.reset}\n`)
|
|
82
|
+
|
|
83
|
+
for (const component of names) {
|
|
84
|
+
const meta = componentList[component]
|
|
85
|
+
const deps = meta.dependencies
|
|
86
|
+
const dependencies = deps.length > 0 ? deps.join(", ") : "none"
|
|
87
|
+
const installed = isComponentInstalled(projectRoot, component, meta.path)
|
|
88
|
+
const status = installed
|
|
89
|
+
? `${COLORS.green}[installed]${COLORS.reset}`
|
|
90
|
+
: `${COLORS.dim}[not installed]${COLORS.reset}`
|
|
91
|
+
|
|
92
|
+
if (installed) installedCount++
|
|
93
|
+
|
|
46
94
|
console.log(
|
|
47
|
-
`${COLORS.green}
|
|
95
|
+
`${COLORS.green}${component}${COLORS.reset} ${status} ${COLORS.dim}(dependencies: ${dependencies})${COLORS.reset}`,
|
|
48
96
|
)
|
|
49
97
|
}
|
|
98
|
+
|
|
99
|
+
console.log(
|
|
100
|
+
`\n${COLORS.dim}${installedCount}/${names.length} components already in this project.${COLORS.reset}`,
|
|
101
|
+
)
|
|
50
102
|
}
|
|
51
103
|
|
|
52
|
-
// Execute the main function
|
|
53
104
|
main().catch((error) => {
|
|
54
105
|
console.error(`${COLORS.red}[tailjng CLI] Unexpected error:${COLORS.reset}`, error)
|
|
55
106
|
process.exit(1)
|
|
@@ -1,156 +1,9 @@
|
|
|
1
|
-
// components-list.js
|
|
2
|
-
|
|
3
|
-
function getComponentList() {
|
|
4
|
-
return {
|
|
5
|
-
'mode-toggle': {
|
|
6
|
-
path: "src/lib/components/mode-toggle",
|
|
7
|
-
dependencies: [],
|
|
8
|
-
},
|
|
9
|
-
'color': {
|
|
10
|
-
path: "src/lib/components/color",
|
|
11
|
-
dependencies: [],
|
|
12
|
-
},
|
|
13
|
-
'tooltip': {
|
|
14
|
-
path: "src/lib/components/tooltip",
|
|
15
|
-
dependencies: [],
|
|
16
|
-
},
|
|
17
|
-
'coach-mark': {
|
|
18
|
-
path: "src/lib/components/coach-mark",
|
|
19
|
-
dependencies: [],
|
|
20
|
-
},
|
|
21
|
-
'badge': {
|
|
22
|
-
path: "src/lib/components/badge",
|
|
23
|
-
dependencies: ["tooltip"],
|
|
24
|
-
},
|
|
25
|
-
'label': {
|
|
26
|
-
path: "src/lib/components/label",
|
|
27
|
-
dependencies: ["tooltip"],
|
|
28
|
-
},
|
|
29
|
-
'toggle-radio': {
|
|
30
|
-
path: "src/lib/components/toggle-radio",
|
|
31
|
-
dependencies: [],
|
|
32
|
-
},
|
|
33
|
-
'button': {
|
|
34
|
-
path: "src/lib/components/button",
|
|
35
|
-
dependencies: ["tooltip", "color"],
|
|
36
|
-
},
|
|
37
|
-
'checkbox-input': {
|
|
38
|
-
path: "src/lib/components/checkbox/checkbox-input",
|
|
39
|
-
dependencies: ["tooltip", "color"],
|
|
40
|
-
},
|
|
41
|
-
'checkbox-switch': {
|
|
42
|
-
path: "src/lib/components/checkbox/checkbox-switch",
|
|
43
|
-
dependencies: ["color"],
|
|
44
|
-
},
|
|
45
|
-
'alert-dialog': {
|
|
46
|
-
path: "src/lib/components/alert/alert-dialog",
|
|
47
|
-
dependencies: ["button", "color"],
|
|
48
|
-
},
|
|
49
|
-
'alert-toast': {
|
|
50
|
-
path: "src/lib/components/alert/alert-toast",
|
|
51
|
-
dependencies: ["button", "color"],
|
|
52
|
-
},
|
|
53
|
-
'progress-bar': {
|
|
54
|
-
path: "src/lib/components/progress-bar",
|
|
55
|
-
dependencies: [],
|
|
56
|
-
},
|
|
57
|
-
'viewer-image': {
|
|
58
|
-
path: "src/lib/components/viewer/viewer-image",
|
|
59
|
-
dependencies: ["button"],
|
|
60
|
-
},
|
|
61
|
-
'viewer-pdf': {
|
|
62
|
-
path: "src/lib/components/viewer/viewer-pdf",
|
|
63
|
-
dependencies: [],
|
|
64
|
-
},
|
|
65
|
-
'dialog': {
|
|
66
|
-
path: "src/lib/components/dialog",
|
|
67
|
-
dependencies: [],
|
|
68
|
-
},
|
|
69
|
-
'input-file': {
|
|
70
|
-
path: "src/lib/components/input/input-file",
|
|
71
|
-
dependencies: [],
|
|
72
|
-
},
|
|
73
|
-
'input-textarea': {
|
|
74
|
-
path: "src/lib/components/input/input-textarea",
|
|
75
|
-
dependencies: [],
|
|
76
|
-
},
|
|
77
|
-
'input-range': {
|
|
78
|
-
path: "src/lib/components/input/input-range",
|
|
79
|
-
dependencies: [],
|
|
80
|
-
},
|
|
81
|
-
'input': {
|
|
82
|
-
path: "src/lib/components/input/input",
|
|
83
|
-
dependencies: [],
|
|
84
|
-
},
|
|
85
|
-
'select-multi-table': {
|
|
86
|
-
path: "src/lib/components/select/select-multi-table",
|
|
87
|
-
dependencies: ["button"],
|
|
88
|
-
},
|
|
89
|
-
'select-multi-dropdown': {
|
|
90
|
-
path: "src/lib/components/select/select-multi-dropdown",
|
|
91
|
-
dependencies: [],
|
|
92
|
-
},
|
|
93
|
-
'select-dropdown': {
|
|
94
|
-
path: "src/lib/components/select/select-dropdown",
|
|
95
|
-
dependencies: [],
|
|
96
|
-
},
|
|
97
|
-
'sidebar-static': {
|
|
98
|
-
path: "src/lib/components/sidebar/sidebar-static",
|
|
99
|
-
dependencies: ["checkbox-switch"],
|
|
100
|
-
},
|
|
101
|
-
'form-container': {
|
|
102
|
-
path: "src/lib/components/form/form-container",
|
|
103
|
-
dependencies: [],
|
|
104
|
-
},
|
|
105
|
-
'form-validation': {
|
|
106
|
-
path: "src/lib/components/form/form-validation",
|
|
107
|
-
dependencies: [],
|
|
108
|
-
},
|
|
109
|
-
'form-sidebar': {
|
|
110
|
-
path: "src/lib/components/form/form-sidebar",
|
|
111
|
-
dependencies: ["tooltip", "button", "checkbox-switch", "coach-mark"],
|
|
112
|
-
},
|
|
113
|
-
'paginator-complete': {
|
|
114
|
-
path: "src/lib/components/paginator/paginator-complete",
|
|
115
|
-
dependencies: ["button"],
|
|
116
|
-
},
|
|
117
|
-
'filter-complete': {
|
|
118
|
-
path: "src/lib/components/filter/filter-complete",
|
|
119
|
-
dependencies: ["select-dropdown", "select-multi-table", "button", "dialog", "checkbox-switch"],
|
|
120
|
-
},
|
|
121
|
-
'card-crud-complete': {
|
|
122
|
-
path: "src/lib/components/card/card-crud-complete",
|
|
123
|
-
dependencies: ["paginator-complete", "filter-complete"],
|
|
124
|
-
},
|
|
125
|
-
'card-complete': {
|
|
126
|
-
path: "src/lib/components/card/card-complete",
|
|
127
|
-
dependencies: ["paginator-complete", "filter-complete"],
|
|
128
|
-
},
|
|
129
|
-
'menu-options-table': {
|
|
130
|
-
path: "src/lib/components/menu/menu-options-table",
|
|
131
|
-
dependencies: ["button"],
|
|
132
|
-
},
|
|
133
|
-
'options-coach-menu': {
|
|
134
|
-
path: "src/lib/components/menu/options-coach-menu",
|
|
135
|
-
dependencies: ["button", "coach-mark"],
|
|
136
|
-
},
|
|
137
|
-
|
|
1
|
+
// components-list.js — reads installable components from registry/components.json
|
|
138
2
|
|
|
3
|
+
const { loadComponentRegistry } = require("./lib-utils")
|
|
139
4
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
path: "src/lib/components/table/table-crud-complete",
|
|
143
|
-
dependencies: ["button", "paginator-complete", "filter-complete", "checkbox-input", "options-coach-menu", "dialog", "viewer-image", "select-dropdown", "input"],
|
|
144
|
-
},
|
|
145
|
-
'table-complete': {
|
|
146
|
-
path: "src/lib/components/table/table-complete",
|
|
147
|
-
dependencies: ["button", "paginator-complete", "filter-complete", "checkbox-input", "options-coach-menu", "dialog", "viewer-image", "select-dropdown", "input"],
|
|
148
|
-
},
|
|
149
|
-
'theme-generator': {
|
|
150
|
-
path: "src/lib/components/theme-generator",
|
|
151
|
-
dependencies: ["input", "input-range", "button", "label", "form-container"],
|
|
152
|
-
},
|
|
153
|
-
}
|
|
5
|
+
function getComponentList() {
|
|
6
|
+
return loadComponentRegistry(__dirname)
|
|
154
7
|
}
|
|
155
8
|
|
|
156
9
|
module.exports = { getComponentList }
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
// header-generator.js
|
|
1
|
+
// header-generator.js — prepends attribution header when copying components into consumer apps
|
|
2
2
|
|
|
3
3
|
const path = require("path")
|
|
4
|
+
const { getPackageVersion } = require("./lib-utils")
|
|
4
5
|
|
|
5
6
|
function generateHeaderComment(fileName) {
|
|
6
|
-
|
|
7
|
+
const version = getPackageVersion(__dirname)
|
|
8
|
+
const headerContent = `===============================================
|
|
7
9
|
Component and Function Library - tailjNg
|
|
8
10
|
===============================================
|
|
9
11
|
Description:
|
|
@@ -27,18 +29,15 @@ Authors:
|
|
|
27
29
|
License:
|
|
28
30
|
This project is licensed under the BSD 3-Clause - see the LICENSE file for more details.
|
|
29
31
|
|
|
30
|
-
Version:
|
|
32
|
+
Version: ${version}
|
|
31
33
|
Creation Date: 2025-01-04
|
|
32
34
|
===============================================`
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
const ext = path.extname(fileName).toLowerCase()
|
|
37
|
+
if (ext === ".html") {
|
|
38
|
+
return `<!--\n${headerContent}\n-->`
|
|
39
|
+
}
|
|
36
40
|
return `/*\n${headerContent}\n*/`
|
|
37
|
-
} else if (ext === ".html") {
|
|
38
|
-
return `<!--\n${headerContent}\n-->`
|
|
39
|
-
} else {
|
|
40
|
-
return `/*\n${headerContent}\n*/`
|
|
41
|
-
}
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
module.exports = { generateHeaderComment }
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// lib-utils.js — shared helpers for package version and project config
|
|
2
|
+
|
|
3
|
+
const fs = require("fs")
|
|
4
|
+
const path = require("path")
|
|
5
|
+
|
|
6
|
+
function readJsonFile(filePath) {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"))
|
|
9
|
+
} catch {
|
|
10
|
+
return null
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Resolves tailjng package root from any CLI module location.
|
|
16
|
+
* Works in source (projects/tailjng/cli/...) and published (node_modules/tailjng/cli/...).
|
|
17
|
+
*/
|
|
18
|
+
function getPackageRoot(fromDir = __dirname) {
|
|
19
|
+
let dir = fromDir
|
|
20
|
+
for (let i = 0; i < 6; i++) {
|
|
21
|
+
const pkgPath = path.join(dir, "package.json")
|
|
22
|
+
if (fs.existsSync(pkgPath)) {
|
|
23
|
+
const pkg = readJsonFile(pkgPath)
|
|
24
|
+
if (pkg?.name === "tailjng") {
|
|
25
|
+
return dir
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const parent = path.dirname(dir)
|
|
29
|
+
if (parent === dir) break
|
|
30
|
+
dir = parent
|
|
31
|
+
}
|
|
32
|
+
return path.join(fromDir, "..", "..")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getPackageVersion(fromDir = __dirname) {
|
|
36
|
+
const pkgPath = path.join(getPackageRoot(fromDir), "package.json")
|
|
37
|
+
const pkg = readJsonFile(pkgPath)
|
|
38
|
+
return pkg?.version ?? "unknown"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getRegistryPath(fromDir = __dirname) {
|
|
42
|
+
return path.join(getPackageRoot(fromDir), "registry", "components.json")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function loadComponentRegistry(fromDir = __dirname) {
|
|
46
|
+
const registryPath = getRegistryPath(fromDir)
|
|
47
|
+
const registry = readJsonFile(registryPath)
|
|
48
|
+
if (!registry?.components) {
|
|
49
|
+
throw new Error(`Component registry not found or invalid: ${registryPath}`)
|
|
50
|
+
}
|
|
51
|
+
return registry.components
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getTailjngConfig(projectRoot) {
|
|
55
|
+
return readJsonFile(path.join(projectRoot, ".tailjng", "paths.json"))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getComponentsBasePath(projectRoot) {
|
|
59
|
+
const config = getTailjngConfig(projectRoot)
|
|
60
|
+
const componentsPath = config?.components ?? "src/app/tailjng"
|
|
61
|
+
return path.join(projectRoot, componentsPath)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Returns all transitive dependencies for a component in install order.
|
|
66
|
+
*/
|
|
67
|
+
function collectDependencyTree(componentName, componentList, collected = [], visited = new Set()) {
|
|
68
|
+
const component = componentList[componentName]
|
|
69
|
+
if (!component) return collected
|
|
70
|
+
|
|
71
|
+
for (const dep of component.dependencies ?? []) {
|
|
72
|
+
if (visited.has(dep)) continue
|
|
73
|
+
visited.add(dep)
|
|
74
|
+
collectDependencyTree(dep, componentList, collected, visited)
|
|
75
|
+
collected.push(dep)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return collected
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = {
|
|
82
|
+
getPackageRoot,
|
|
83
|
+
getPackageVersion,
|
|
84
|
+
getRegistryPath,
|
|
85
|
+
loadComponentRegistry,
|
|
86
|
+
getTailjngConfig,
|
|
87
|
+
getComponentsBasePath,
|
|
88
|
+
collectDependencyTree,
|
|
89
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// overwrite-policy.js — session overwrite strategy for component installs
|
|
2
|
+
|
|
3
|
+
/** @type {'ask' | 'all' | 'skip' | null} */
|
|
4
|
+
let policy = null
|
|
5
|
+
|
|
6
|
+
function getOverwritePolicy() {
|
|
7
|
+
return policy
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function setOverwritePolicy(value) {
|
|
11
|
+
policy = value
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function resetOverwritePolicy() {
|
|
15
|
+
policy = null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = { getOverwritePolicy, setOverwritePolicy, resetOverwritePolicy }
|
|
@@ -1,25 +1,15 @@
|
|
|
1
|
-
// path-utils.js
|
|
1
|
+
// path-utils.js — maps registry paths to consumer app install locations
|
|
2
2
|
|
|
3
|
+
const fs = require("fs")
|
|
3
4
|
const path = require("path")
|
|
5
|
+
const { getComponentsBasePath } = require("./lib-utils")
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
* Extracts folder structure information from the component path
|
|
7
|
-
* @param {string} componentPath - Path del componente (ej: "src/lib/components/alert/dialog-alert")
|
|
8
|
-
* @returns {object} - Information about the folder structure
|
|
9
|
-
*/
|
|
10
|
-
function parseComponentPath(componentPath) {
|
|
11
|
-
|
|
12
|
-
// Remove the base prefix "src/lib/components/"
|
|
13
|
-
const basePath = "src/lib/components/"
|
|
14
|
-
const relativePath = componentPath.replace(basePath, "")
|
|
7
|
+
const COMPONENTS_SOURCE_PREFIX = "src/lib/components/"
|
|
15
8
|
|
|
16
|
-
|
|
9
|
+
function parseComponentPath(componentPath) {
|
|
10
|
+
const relativePath = componentPath.replace(COMPONENTS_SOURCE_PREFIX, "")
|
|
17
11
|
const pathParts = relativePath.split("/")
|
|
18
|
-
|
|
19
|
-
// The last element is the component name
|
|
20
12
|
const componentFolder = pathParts[pathParts.length - 1]
|
|
21
|
-
|
|
22
|
-
// All except the last element are subfolders
|
|
23
13
|
const subfolders = pathParts.slice(0, -1)
|
|
24
14
|
|
|
25
15
|
return {
|
|
@@ -30,23 +20,18 @@ function parseComponentPath(componentPath) {
|
|
|
30
20
|
}
|
|
31
21
|
}
|
|
32
22
|
|
|
33
|
-
/**
|
|
34
|
-
* Make sure to keep the folder structure
|
|
35
|
-
* @param {string} projectRoot - Project root directory
|
|
36
|
-
* @param {string} componentName - Component name
|
|
37
|
-
* @param {string} componentPath - Original component path
|
|
38
|
-
* @returns {string} - Full target path
|
|
39
|
-
*/
|
|
40
23
|
function buildTargetPath(projectRoot, componentName, componentPath) {
|
|
41
24
|
const pathInfo = parseComponentPath(componentPath)
|
|
25
|
+
const basePath = getComponentsBasePath(projectRoot)
|
|
42
26
|
|
|
43
27
|
if (pathInfo.hasSubfolders) {
|
|
44
|
-
|
|
45
|
-
return path.join(projectRoot, "src", "app", "tailjng", pathInfo.fullSubPath, componentName)
|
|
46
|
-
} else {
|
|
47
|
-
// If it doesn't have subfolders, use the original structure
|
|
48
|
-
return path.join(projectRoot, "src", "app", "tailjng", componentName)
|
|
28
|
+
return path.join(basePath, pathInfo.fullSubPath, componentName)
|
|
49
29
|
}
|
|
30
|
+
return path.join(basePath, componentName)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isComponentInstalled(projectRoot, componentName, componentPath) {
|
|
34
|
+
return fs.existsSync(buildTargetPath(projectRoot, componentName, componentPath))
|
|
50
35
|
}
|
|
51
36
|
|
|
52
|
-
module.exports = { parseComponentPath, buildTargetPath }
|
|
37
|
+
module.exports = { parseComponentPath, buildTargetPath, isComponentInstalled }
|