Skip to content

Commit

Permalink
Merge pull request #27 from ngx-primer/feature/accordion
Browse files Browse the repository at this point in the history
Feature/accordion
  • Loading branch information
elhakimdev authored Dec 21, 2024
2 parents d0d1884 + ff83941 commit 0a8e3ca
Show file tree
Hide file tree
Showing 29 changed files with 166 additions and 124 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
name: 'Dependency review'
on:
pull_request:
branches: [ "main" ]
branches: ['main']

# If using a dependency submission action in this workflow this permission will need to be set to:
#
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/greetings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: "Message that will be displayed on users' first issue"
pr-message: "Message that will be displayed on users' first pull request"
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: "Message that will be displayed on users' first issue"
pr-message: "Message that will be displayed on users' first pull request"
17 changes: 17 additions & 0 deletions .github/workflows/nx-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,20 @@ jobs:
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
# When you enable task distribution, run the e2e-ci task instead of e2e
- run: pnpm exec nx affected -t lint test build e2e

- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false

- name: Publish to npm
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
pnpm publish --access public
6 changes: 6 additions & 0 deletions apps/playground/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
>
Collapse All
</button>
<button
(click)="accordionRoot.toogleAllValue()"
class="bg-yellow-500 text-white py-2 px-4 rounded-md hover:bg-yellow-600 focus:outline-none focus:ring-2 focus:ring-yellow-400"
>
Toogle All
</button>
</div>
<ngx-primer-accordion-root
#accordionRoot
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
<ng-content>

</ng-content>
<ng-content> </ng-content>
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ import { NgxPrimerIdGeneratorDirective } from '@ngx-primer/primitive/utilities';
inputs: ['ngxPrimerIdAttr'],
},
{
directive: NgxPrimerAccordionContentContextDirective
}
directive: NgxPrimerAccordionContentContextDirective,
},
],
})
export class NgxPrimerAccordionContentComponent<T> implements OnInit {
Expand Down Expand Up @@ -95,7 +95,7 @@ export class NgxPrimerAccordionContentComponent<T> implements OnInit {
protected runInitializationFn(doneFn?: <P>(args?: P) => void): void {
if (doneFn) {
doneFn({
context: this.accordionContentContext
context: this.accordionContentContext,
});
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
<ng-content>
</ng-content>
<ng-content> </ng-content>
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ import { NgxPrimerIdGeneratorDirective } from '@ngx-primer/primitive/utilities';
inputs: ['ngxPrimerIdAttr'],
},
{
directive: NgxPrimerAccordionItemContextDirective
}
directive: NgxPrimerAccordionItemContextDirective,
},
],
})
export class NgxPrimerAccordionItemComponent<T> implements OnInit {
Expand Down Expand Up @@ -91,16 +91,15 @@ export class NgxPrimerAccordionItemComponent<T> implements OnInit {
}
);

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


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

public readonly isOpen = computed<boolean>(() =>
Expand Down Expand Up @@ -168,9 +167,11 @@ export class NgxPrimerAccordionItemComponent<T> implements OnInit {
protected runInitializationFn(doneFn?: <P>(args?: P) => void): void {
if (doneFn) {
// ensure context being initalized
setTimeout(() => doneFn({
context: this.accordionItemContext
}));
setTimeout(() =>
doneFn({
context: this.accordionItemContext,
})
);
}
}

Expand All @@ -184,7 +185,7 @@ export class NgxPrimerAccordionItemComponent<T> implements OnInit {
?.instance as NgxPrimerAccordionRootComponent<T>;
}

focus(){
focus() {
this.accordionTrigger()?.focus();
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
<ng-content>
</ng-content>
<ng-content> </ng-content>
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe('NgxPrimerAccordionRootComponent', () => {

for (const key in config) {
const keyName = key as keyof typeof config;
if(typeof config[keyName] === 'function') return; // skip function;
if (typeof config[keyName] === 'function') return; // skip function;
expect(component.accordionConfig[keyName]).toEqual(config[keyName]);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,10 @@ export class NgxPrimerAccordionRootComponent<T> implements OnInit {
this.toggleAll(false);
}

public toogleAllValue() {
this.toggleAll();
}

/**
* Toggles the open/closed state of all accordion items based on the provided `isOpen` value.
*
Expand All @@ -583,20 +587,18 @@ export class NgxPrimerAccordionRootComponent<T> implements OnInit {
* - `false`: Collapses all accordion items.
* @returns {void} This method does not return anything. It only updates the open/closed state of all items.
*/
private toggleAll(isOpen: boolean) {
private toggleAll(isOpen?: boolean) {
if (this.type() === 'Single' || this.disabled()) return;

this.accordionItems().forEach(({ disabled, value }) => {
const isItemDisabled = disabled();
if (isItemDisabled) return;
this.toogleMultiple(value(), !isOpen);
if (disabled()) return;
this.toogleMultiple(value(), isOpen ?? this.isOpen(value()));
});
}


/**
* Expands the accordion with the given value(s).
*
*
* If the value is currently collapsed, it will be expanded.
* If the value is currently expanded, it will remain expanded.
*
Expand All @@ -608,7 +610,7 @@ export class NgxPrimerAccordionRootComponent<T> implements OnInit {

/**
* Collapses the specified value(s) in the accordion.
*
*
* If the value is currently expanded, it will be collapsed.
* If the value is currently collapsed, it will remain collapsed.
*
Expand All @@ -618,13 +620,12 @@ export class NgxPrimerAccordionRootComponent<T> implements OnInit {
this.toggleValue(value, false);
}


/**
* Toggles the expansion state of the given value(s).
*
*
* If the value is currently collapsed, it will be expanded.
* If the value is currently expanded, it will be collapsed.
*
*
* @protected
* @param {T | T[]} value - The value or array of values to toggle.
* @param {boolean} isExpanding - A flag indicating whether to expand (true) or collapse (false) the value(s).
Expand All @@ -649,7 +650,7 @@ export class NgxPrimerAccordionRootComponent<T> implements OnInit {

/**
* Enables the specified value(s) by updating their disable state.
*
*
* If the value is currently disabled, it will be enabled.
* If the value is currently enabled, it will remain enabled.
*
Expand All @@ -663,10 +664,10 @@ export class NgxPrimerAccordionRootComponent<T> implements OnInit {

/**
* Disables the specified value(s) by updating their disable state.
*
*
* If the value is currently enabled, it will be disabled.
* If the value is currently disabled, it will remain disabled.
*
*
* @public
* @method
* @param value - The value or array of values to be disabled.
Expand All @@ -678,28 +679,33 @@ export class NgxPrimerAccordionRootComponent<T> implements OnInit {

/**
* Updates the disable state of the specified value(s).
*
*
* If the value is currently disabled, it will be enabled.
* If the value is currently enabled, it will be disabled.
*
*
* @protected
* @param {T | T[]} value - The value or array of values to update.
* @param {boolean} enable - A flag indicating whether to enable (true) or disable (false) the value(s).
*/
protected updateDisableState(value: T | T[], enable: boolean) {
const values = Array.isArray(value) ? value : [value];

const accordionItems = this.accordionItems().filter((item) => values.includes(item.value()));

const update = (item: NgxPrimerAccordionItemComponent<T>, enable: boolean) => {

const accordionItems = this.accordionItems().filter((item) =>
values.includes(item.value())
);

const update = (
item: NgxPrimerAccordionItemComponent<T>,
enable: boolean
) => {
const isDisabled = item.disabled();
const shouldDisable = !enable;

if (isDisabled !== shouldDisable) {
item.disabled.set(shouldDisable ? true : false);
}
};

accordionItems.forEach((item) => update(item, enable));
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
<ng-content>
</ng-content>
<ng-content> </ng-content>
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,9 @@ export class NgxPrimerAccordionTriggerComponent<T> implements OnInit {
}

@HostListener('click')
toogle() {
if (this.accordionRoot?.disabled() || this.accordionItem?.disabled()) return;
public toogle() {
if (this.accordionRoot?.disabled() || this.accordionItem?.disabled())
return;
this.accordionRoot?.toggle(this.accordionItem?.value() as T);
}

Expand Down Expand Up @@ -326,8 +327,9 @@ export class NgxPrimerAccordionTriggerComponent<T> implements OnInit {
?.instance as NgxPrimerAccordionContentComponent<T>;
}

focus() {
if(this.accordionRoot?.disabled() || this.accordionItem?.disabled()) return;
public focus() {
if (this.accordionRoot?.disabled() || this.accordionItem?.disabled())
return;
(this.viewContainerRef.element.nativeElement as HTMLElement).focus({
preventScroll: false,
});
Expand Down
2 changes: 1 addition & 1 deletion packages/primitives/accordion/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from './accordion-root/accordion-root.component';
export * from './accordion-item/accordion-item.component';
export * from './accordion-content/accordion-content.component';
export * from './accordion-trigger/accordion-trigger.component';
export * from './accordion-trigger/accordion-trigger.component';
24 changes: 17 additions & 7 deletions packages/primitives/accordion/src/configs/accordion-config.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { NgxPrimerAccordionConfig, NgxPrimerAccordionOrientation, NgxPrimerAccordionType, defaultAccordionConfig, provideAccordionConfig } from './accordion-config';
import {
NgxPrimerAccordionConfig,
NgxPrimerAccordionOrientation,
NgxPrimerAccordionType,
defaultAccordionConfig,
provideAccordionConfig,
} from './accordion-config';

import { NgxPrimerAccordionConfigToken } from '../tokens/accordion-config.token';
import { TestBed } from '@angular/core/testing';
Expand Down Expand Up @@ -52,10 +58,12 @@ describe('AccordionConfig', () => {

it('should provide custom config', () => {
TestBed.configureTestingModule({
providers: [provideAccordionConfig({
type: NgxPrimerAccordionType.Single,
collapsible: false,
})],
providers: [
provideAccordionConfig({
type: NgxPrimerAccordionType.Single,
collapsible: false,
}),
],
});
const injectedConfig = TestBed.inject(NgxPrimerAccordionConfigToken);
expect(injectedConfig.type).toBe(NgxPrimerAccordionType.Single);
Expand All @@ -69,7 +77,9 @@ describe('AccordionConfig', () => {
const injectedConfig = TestBed.inject(NgxPrimerAccordionConfigToken);
expect(injectedConfig.type).toBe(NgxPrimerAccordionType.Multiple);
expect(injectedConfig.collapsible).toBe(true);
expect(injectedConfig.orientation).toBe(NgxPrimerAccordionOrientation.Vertical);
expect(injectedConfig.orientation).toBe(
NgxPrimerAccordionOrientation.Vertical
);
expect(injectedConfig.theme.builtIn).toBe(true);
});
});
});
23 changes: 17 additions & 6 deletions packages/primitives/accordion/src/configs/accordion-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ export interface NgxPrimerAccordionConfig {
builtIn: boolean;
};
// Overloaded method signatures
updateConfig(callbackFn: (config: NgxPrimerAccordionConfig) => Partial<NgxPrimerAccordionConfig>): void;
updateConfig(
callbackFn: (
config: NgxPrimerAccordionConfig
) => Partial<NgxPrimerAccordionConfig>
): void;
updateConfig(newConfig: Partial<NgxPrimerAccordionConfig>): void;
resetConfig(target: NgxPrimerAccordionConfig): void
resetConfig(target: NgxPrimerAccordionConfig): void;
}
export const defaultAccordionConfig: () => NgxPrimerAccordionConfig = () => ({
type: 'Multiple',
Expand All @@ -31,13 +35,20 @@ export const defaultAccordionConfig: () => NgxPrimerAccordionConfig = () => ({
theme: {
builtIn: true,
},
updateConfig(callbackFn: Partial<NgxPrimerAccordionConfig> | ((config: NgxPrimerAccordionConfig) => Partial<NgxPrimerAccordionConfig>)): void {
const updatedConfig = typeof callbackFn === 'function' ? callbackFn(this) : {...callbackFn};
Object.assign(this, {...updatedConfig});
updateConfig(
callbackFn:
| Partial<NgxPrimerAccordionConfig>
| ((
config: NgxPrimerAccordionConfig
) => Partial<NgxPrimerAccordionConfig>)
): void {
const updatedConfig =
typeof callbackFn === 'function' ? callbackFn(this) : { ...callbackFn };
Object.assign(this, { ...updatedConfig });
},
resetConfig(target: NgxPrimerAccordionConfig): void {
Object.assign(target, defaultAccordionConfig());
}
},
});
export function provideAccordionConfig(
config: Partial<NgxPrimerAccordionConfig>
Expand Down
Loading

0 comments on commit 0a8e3ca

Please sign in to comment.