Skip to content

Commit

Permalink
Merge pull request #23 from ngx-primer/feature/plugins
Browse files Browse the repository at this point in the history
Feature/plugins
  • Loading branch information
elhakimdev authored Dec 17, 2024
2 parents 8e67ede + 79210b1 commit 351c1d2
Show file tree
Hide file tree
Showing 15 changed files with 9,622 additions and 3,345 deletions.
64 changes: 35 additions & 29 deletions apps/playground/server.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,54 @@
import 'zone.js/node';

import { dirname, resolve } from 'node:path';

import { APP_BASE_HREF } from '@angular/common';
import { CommonEngine } from '@angular/ssr';
import bootstrap from './src/main.server'; // Server bootstrap module
import express from 'express';
import { fileURLToPath } from 'node:url';
import { dirname, join, resolve } from 'node:path';
import bootstrap from './src/main.server';
import { renderApplication } from '@angular/platform-server';

// The Express app is exported so that it can be used by serverless Functions.
// Export the Express app so it can be used for serverless functions
export function app(): express.Express {
const server = express();

const serverDistFolder = dirname(fileURLToPath(import.meta.url));
const browserDistFolder = resolve(serverDistFolder, '../browser');
const indexHtml = join(serverDistFolder, 'index.server.html');

const commonEngine = new CommonEngine();
const indexHtml = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Angular SSR</title>
</head>
<body>
<app-root></app-root>
</body>
</html>`;

server.set('view engine', 'html');
server.set('views', browserDistFolder);

// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
// Serve static files from the browser folder
server.get(
'**',
'*.*',
express.static(browserDistFolder, {
maxAge: '1y',
index: 'index.html',
})
);

// All regular routes use the Angular engine
server.get('**', (req, res, next) => {
const { protocol, originalUrl, baseUrl, headers } = req;

commonEngine
.render({
bootstrap,
documentFilePath: indexHtml,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: browserDistFolder,
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
})
.then((html) => res.send(html))
.catch((err) => next(err));
// All routes render the Angular application
server.get('**', async (req, res, next) => {
try {
const html = await renderApplication(bootstrap, {
document: indexHtml,
url: req.originalUrl,
platformProviders: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }],
});

res.send(html);
} catch (err) {
console.error(err);
next(err);
}
});

return server;
Expand All @@ -50,7 +57,6 @@ export function app(): express.Express {
function run(): void {
const port = process.env['PORT'] || 4000;

// Start up the Node server
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
Expand Down
120 changes: 69 additions & 51 deletions apps/playground/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,56 +1,74 @@
<div class="py-5 flex flex-row gap-x-3 w-full h-full text-sm text-left">
<ngx-primer-accordion-root
#accordionRoot
[ngxPrimerIdAttr]="'accordion-overview'"
[(ngxPrimerAccordionValue)]="accordionVal"
[ngxPrimerAccordionType]="'Multiple'"
class="flex min-w-[360px] w-[360px] h-full flex-col border rounded-md shadow-sm shadow-gray-300 border-opacity-50 border-gray-400 overflow-hidden"
>
@for (item of accordionData; track $index) {
<ngx-primer-accordion-item
#accordionItem
[ngxPrimerIdAttr]="'accordion-overview-item-' + item.value"
[ngxPrimerAccordionItemValue]="item.value"
class="flex border-b flex-col"
>
<ngx-primer-accordion-trigger
#accordionTrigger
[ngxPrimerIdAttr]="'accordion-overview-trigger-' + item.value"
class="flex flex-row w-full justify-between p-2 cursor-pointer hover:bg-gray-100 focus:outline-none focus:bg-slate-100"
[ngClass]="{
'border-b': accordionItem.isOpen()
}"
<div class="flex flex-col gap-y-2">
<div class="flex flex-row w-full justify-between">
<button
(click)="accordionRoot.expandAll()"
class="bg-orange-500 text-white py-2 px-4 rounded-md hover:bg-orange-600 focus:outline-none focus:ring-2 focus:ring-orange-400"
>
<div class="text-gray-800">
{{ item.label }}
</div>
<div>
<ng-icon
#accordionTrigerIcon
[name]="'heroChevronDownMini'"
class="transition-all ease-in-out duration-300"
[ngClass]="{
'transform -rotate-180': accordionItem.isOpen()
}"
/>
</div>
</ngx-primer-accordion-trigger>
<ngx-primer-accordion-content
#accordionContent
ngxPrimerCollapsibleDirective
[ngxPrimerIdAttr]="'accordion-overview-content-' + item.value"
[ngxPrimerCollapsed]="!accordionItem.isOpen()"
[ngxPrimerCollapsibleDirection]="accordionRoot.orientation()"
class="text-gray-500 overflow-hidden"
Expand All
</button>
<button
(click)="accordionRoot.collapseAll()"
class="bg-purple-500 text-white py-2 px-4 rounded-md hover:bg-purple-600 focus:outline-none focus:ring-2 focus:ring-purple-400"
>
<!-- {{ accordionContent.idGenerator()?.generatedId | json }} -->
<span>
{{ item.content }}
</span>
</ngx-primer-accordion-content>
</ngx-primer-accordion-item>
}
</ngx-primer-accordion-root>
Collapse All
</button>
</div>
<ngx-primer-accordion-root
#accordionRoot
[ngxPrimerIdAttr]="'accordion-overview'"
[(ngxPrimerAccordionValue)]="accordionVal"
[ngxPrimerAccordionType]="'Multiple'"
[ngxPrimerAccordionDisabled]="false"
class="flex min-w-[360px] w-[360px] h-full flex-col border rounded-md shadow-sm shadow-gray-300 border-opacity-50 border-gray-400 overflow-hidden"
>
@for (item of accordionData; track $index) {
<ngx-primer-accordion-item
[(ngxPrimerAccordionItemDisabled)]="disabled"
#accordionItem
[ngxPrimerIdAttr]="'accordion-overview-item-' + item.value"
[ngxPrimerAccordionItemValue]="item.value"
class="flex border-b flex-col"
>
<ngx-primer-accordion-trigger
#accordionTrigger
[ngxPrimerIdAttr]="'accordion-overview-trigger-' + item.value"
class="flex flex-row w-full justify-between p-2 cursor-pointer hover:bg-gray-100 focus:outline-none focus:bg-slate-100"
[ngClass]="{
'border-b': accordionItem.isOpen()
}"
>
<div class="text-gray-800">
{{ item.label }}
</div>
<div>
<ng-icon
#accordionTrigerIcon
[name]="'heroChevronDownMini'"
class="transition-all ease-in-out duration-300"
[ngClass]="{
'transform -rotate-180': accordionItem.isOpen()
}"
/>
</div>
</ngx-primer-accordion-trigger>
<ngx-primer-accordion-content
#accordionContent
ngxPrimerCollapsibleDirective
[ngxPrimerIdAttr]="'accordion-overview-content-' + item.value"
[ngxPrimerCollapsed]="!accordionItem.isOpen()"
[ngxPrimerCollapsibleDirection]="accordionRoot.orientation()"
class="text-gray-500 overflow-hidden"
>
<!-- {{ accordionContent.idGenerator()?.generatedId | json }} -->
<span>
{{ item.content }}
</span>
</ngx-primer-accordion-content>
</ngx-primer-accordion-item>
}
</ngx-primer-accordion-root>
</div>

<ngx-primer-accordion-root
#accordionRoot2
Expand Down Expand Up @@ -104,4 +122,4 @@
</ngx-primer-accordion-item>
}
</ngx-primer-accordion-root>
</div>
</div>
2 changes: 2 additions & 0 deletions apps/playground/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,6 @@ export class AppComponent {
] as const;

accordion2Val = this.accordion2Data[1].value;

disabled = true;
}
2 changes: 1 addition & 1 deletion apps/playground/src/main.server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { bootstrapApplication } from '@angular/platform-browser';
import { config } from './app/app.config.server';

const bootstrap = () => bootstrapApplication(AppComponent, config);
Expand Down
3 changes: 1 addition & 2 deletions packages/primitives/accordion/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
"executor": "@nx/angular:package",
"outputs": ["{workspaceRoot}/dist/{projectRoot}"],
"options": {
"project": "packages/primitives/accordion//ng-package.json",
"tailwindConfig": "packages/primitives/accordion/tailwind.config.js"
"project": "packages/primitives/accordion//ng-package.json"
},
"configurations": {
"production": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @angular-eslint/no-input-rename */
/**
* Copyright [2024] [ElhakimDev]
*
Expand All @@ -22,7 +21,7 @@ import {
computed,
contentChild,
inject,
input,
model,
} from '@angular/core';

import { CommonModule } from '@angular/common';
Expand Down Expand Up @@ -92,12 +91,20 @@ export class NgxPrimerAccordionItemComponent<T> implements OnInit {
}
);

public readonly value = input.required<T>({
public readonly value = model<T|null>(null, {
alias: 'ngxPrimerAccordionItemValue',
});


/**
* Whether the accordion item is disabled.
*/
public readonly disabled = model(false, {
alias: 'ngxPrimerAccordionItemDisabled'
});

public readonly isOpen = computed<boolean>(() =>
this.accordionRoot?.isOpen(this.value())
this.accordionRoot?.isOpen(this.value() as T)
);

@HostBinding('attr.data-orientation')
Expand Down
Loading

0 comments on commit 351c1d2

Please sign in to comment.