Skip to content

Commit

Permalink
Merge pull request #249 from laws-africa/toc
Browse files Browse the repository at this point in the history
Simplify TOC item rendering and allow customisation of expand/collapse
  • Loading branch information
longhotsummer authored May 5, 2023
2 parents 05d8cbe + 2cea83a commit de4bab8
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 78 deletions.
20 changes: 18 additions & 2 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ export namespace Components {
* Expands all items
*/
"expandAll": () => Promise<void>;
/**
* Should items be expanded by default? This can be overridden by setting the expanded property for individual items.
*/
"expanded": boolean;
/**
* Fetch content from Laws.Africa services? Requires a Laws.Africa partnership and the frbrExpressionUri property to be set.
*/
Expand All @@ -162,7 +166,7 @@ export namespace Components {
*/
"frbrExpressionUri"?: string;
/**
* JSON value or string value parsed to array of items used to build the table of contents. Each item must have a `title` attribute (which may be `null`), and a `children` attribute (which may be `null`).
* JSON value or string value parsed to array of items used to build the table of contents. Each item must have a `title` attribute (which may be `null`), and a `children` attribute (which may be `null`). Items may optionally have an id attribute and an href attribute, which are used to build the links for each item.
*/
"items": TOCItem[] | string;
/**
Expand Down Expand Up @@ -195,6 +199,10 @@ export namespace Components {
* Button text for expand all button
*/
"expandAllBtnText": string;
/**
* Should the table of contents be expanded when first created?
*/
"expanded": boolean;
/**
* Fetch content from Laws.Africa services? Requires a Laws.Africa partnership and the frbrExpressionUri property to be set.
*/
Expand Down Expand Up @@ -476,6 +484,10 @@ declare namespace LocalJSX {
"onLaItemChanged"?: (event: LaGutterItemCustomEvent<void>) => void;
}
interface LaTableOfContents {
/**
* Should items be expanded by default? This can be overridden by setting the expanded property for individual items.
*/
"expanded"?: boolean;
/**
* Fetch content from Laws.Africa services? Requires a Laws.Africa partnership and the frbrExpressionUri property to be set.
*/
Expand All @@ -485,7 +497,7 @@ declare namespace LocalJSX {
*/
"frbrExpressionUri"?: string;
/**
* JSON value or string value parsed to array of items used to build the table of contents. Each item must have a `title` attribute (which may be `null`), and a `children` attribute (which may be `null`).
* JSON value or string value parsed to array of items used to build the table of contents. Each item must have a `title` attribute (which may be `null`), and a `children` attribute (which may be `null`). Items may optionally have an id attribute and an href attribute, which are used to build the links for each item.
*/
"items"?: TOCItem[] | string;
/**
Expand Down Expand Up @@ -518,6 +530,10 @@ declare namespace LocalJSX {
* Button text for expand all button
*/
"expandAllBtnText"?: string;
/**
* Should the table of contents be expanded when first created?
*/
"expanded"?: boolean;
/**
* Fetch content from Laws.Africa services? Requires a Laws.Africa partnership and the frbrExpressionUri property to be set.
*/
Expand Down
1 change: 0 additions & 1 deletion core/src/components/table-of-contents-controller/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ Click [here](https://laws.africa/la-web-components/?path=/docs/library-la-table-
graph TD;
la-table-of-contents-controller --> la-table-of-contents
la-table-of-contents --> la-toc-item
la-toc-item --> la-toc-item
style la-table-of-contents-controller fill:#f9f,stroke:#333,stroke-width:4px
```

Expand Down
1 change: 1 addition & 0 deletions core/src/components/table-of-contents/fixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"title": "Ch. 1 – ",
"index": 3,
"append_icon": "😝",
"expanded": false,
"children": [
{
"num": "A",
Expand Down
19 changes: 9 additions & 10 deletions core/src/components/table-of-contents/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,15 @@ Click [here](https://laws.africa/la-web-components/?path=/docs/library-la-table-

## Properties

| Property | Attribute | Description | Type | Default |
| ------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ----------- |
| `expanded` | `expanded` | Should the table of contents be expanded when first created? | `boolean` | `true` |
| `fetch` | `fetch` | Fetch content from Laws.Africa services? Requires a Laws.Africa partnership and the frbrExpressionUri property to be set. | `boolean` | `false` |
| `frbrExpressionUri` | `frbr-expression-uri` | Full Akoma Ntoso FRBR Expression URI to fetch TOC information for. Only used if `fetch` is set. | `string \| undefined` | `undefined` |
| `items` | `items` | JSON value or string value parsed to array of items used to build the table of contents. Each item must have a `title` attribute (which may be `null`), and a `children` attribute (which may be `null`). Items may optionally have an id attribute and a url attribute, which are used to build the links for each item. | `TOCItem[] \| string` | `[]` |
| `partner` | `partner` | Partner code to use when fetching content from Laws.Africa. Defaults to the `location.hostname`. | `string \| undefined` | `undefined` |
| `provider` | `provider` | Provider URL for fetching content (advanced usage only). | `string` | `PROVIDER` |
| `titleFilter` | `title-filter` | value to filter items by item title | `string` | `''` |
| Property | Attribute | Description | Type | Default |
| ------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ----------- |
| `expanded` | `expanded` | Should items be expanded by default? This can be overridden by setting the expanded property for individual items. | `boolean` | `true` |
| `fetch` | `fetch` | Fetch content from Laws.Africa services? Requires a Laws.Africa partnership and the frbrExpressionUri property to be set. | `boolean` | `false` |
| `frbrExpressionUri` | `frbr-expression-uri` | Full Akoma Ntoso FRBR Expression URI to fetch TOC information for. Only used if `fetch` is set. | `string \| undefined` | `undefined` |
| `items` | `items` | JSON value or string value parsed to array of items used to build the table of contents. Each item must have a `title` attribute (which may be `null`), and a `children` attribute (which may be `null`). Items may optionally have an id attribute and an href attribute, which are used to build the links for each item. | `TOCItem[] \| string` | `[]` |
| `partner` | `partner` | Partner code to use when fetching content from Laws.Africa. Defaults to the `location.hostname`. | `string \| undefined` | `undefined` |
| `provider` | `provider` | Provider URL for fetching content (advanced usage only). | `string` | `PROVIDER` |
| `titleFilter` | `title-filter` | value to filter items by item title | `string` | `''` |


## Methods
Expand Down Expand Up @@ -182,7 +182,6 @@ Type: `Promise<void>`
```mermaid
graph TD;
la-table-of-contents --> la-toc-item
la-toc-item --> la-toc-item
la-table-of-contents-controller --> la-table-of-contents
style la-table-of-contents fill:#f9f,stroke:#333,stroke-width:4px
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default {
},
};

const Template = () => html`<la-table-of-contents .items="${data.nested_toc_list}"></la-table-of-contents>`;
const Template = () => html`<la-table-of-contents expanded="true" .items="${data.nested_toc_list}"></la-table-of-contents>`;

export const BasicUsage = Template.bind({});
BasicUsage.args = {};
Expand Down
96 changes: 50 additions & 46 deletions core/src/components/table-of-contents/table-of-contents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import { PROVIDER, getPartner } from '../../utils/services';
* and a `children` attribute (which may be `null`).
*/
export interface TOCItem {
[key: string]: any; // type for unknown keys.
title?: string;
id?: string;
url?: string;
href?: string;
expanded?: boolean;
children?: TOCItem[];
}

Expand All @@ -23,7 +23,7 @@ export class TableOfContents {
* JSON value or string value parsed to array of items used to build the table of contents. Each item must have
* a `title` attribute (which may be `null`), and a `children` attribute (which may be `null`).
*
* Items may optionally have an id attribute and a url attribute, which are used to build the links for each item.
* Items may optionally have an id attribute and an href attribute, which are used to build the links for each item.
* */
@Prop() items: TOCItem[] | string = [];

Expand All @@ -32,7 +32,9 @@ export class TableOfContents {
* */
@Prop() titleFilter = '';

/** Should the table of contents be expanded when first created? */
/**
* Should items be expanded by default? This can be overridden by setting the expanded property for individual items.
* */
@Prop() expanded = true;

/** Full Akoma Ntoso FRBR Expression URI to fetch TOC information for. Only used if `fetch` is set. */
Expand All @@ -50,6 +52,9 @@ export class TableOfContents {

@Element() el!: HTMLElement;

protected expandIconHtml = '';
protected collapseIconHtml = '';

@Watch('items')
parseItemsProp(newValue: any) {
if (typeof newValue === 'string') {
Expand Down Expand Up @@ -89,21 +94,32 @@ export class TableOfContents {
}
}

getSlotHTML(selector: string) {
const element = this.el.querySelector(selector);
/**
* If slots originate from `la-table-of-contents`, query for slot html is
* `this.el.querySelector("[slot]").innerHTML`
* If slot originate from `la-table-of-contents-controller` query for slot html is
* `this.el.querySelector("[slot] [slot]").innerHTML`
* */

// Slots originating from la-table-of-content-controller
if (element?.querySelector(selector)) {
return element.querySelector(selector)?.innerHTML || '';
}

// Slots originating from la-table-of-content
return element?.innerHTML || '';
}

componentWillLoad() {
this.expandIconHtml = this.getSlotHTML("[slot='expand-icon']");
this.collapseIconHtml = this.getSlotHTML("[slot='collapse-icon']");
this.parseItemsProp(this.items);
this.titleFilterChanged(this.titleFilter);
this.fetchContent();
}

componentDidLoad() {
// expand or collapse when first loaded
if (this.expanded) {
this.expandAll();
} else {
this.collapseAll();
}
}

/**
* Expands all items
*/
Expand Down Expand Up @@ -178,46 +194,34 @@ export class TableOfContents {
this.expandAll();
}

render() {
const renderTOCItem = (item: TOCItem) => {
const getSlotHTML = (selector: string) => {
const element = this.el.querySelector(selector);
/**
* If slots originate from `la-table-of-contents`, query for slot html is
* `this.el.querySelector("[slot]").innerHTML`
* If slot originate from `la-table-of-contents-controller` query for slot html is
* `this.el.querySelector("[slot] [slot]").innerHTML`
* */

// Slots originating from la-table-of-content-controller
if (element?.querySelector(selector)) {
return element.querySelector(selector)?.innerHTML || '';
}

// Slots originating from la-table-of-content
return element?.innerHTML || '';
};

const expandIcon = getSlotHTML("[slot='expand-icon']");
const collapseIcon = getSlotHTML("[slot='collapse-icon']");
return (
<la-toc-item
item={item}
filteredItems={this.filteredItems}
expandIconHtml={expandIcon}
collapseIconHtml={collapseIcon}
expanded={false}
></la-toc-item>
);
};
/**
* Render items recursively. We render from the bottom up, allowing us to append children into their
* parents. Rendering recursively here rather than inside la-toc-item means we can make use of global
* configuration details without having to pass them down the tree.
*/
renderItem(item: TOCItem) {
// render the children first, so we can add them to the parent
const kids = (item.children || []).map((child) => this.renderItem(child));
// if the item has an explicit expanded value, use that, otherwise use the tree's default value
const expanded = item.expanded === undefined ? this.expanded : item.expanded;

return <la-toc-item
item={item}
filteredItems={this.filteredItems}
expandIconHtml={this.expandIconHtml}
collapseIconHtml={this.collapseIconHtml}
expanded={expanded}
>{kids}</la-toc-item>;
}

render() {
return (
<Host>
<div style={{ display: 'none' }}>
<slot name="expand-icon"></slot>
<slot name="collapse-icon"></slot>
</div>
<div class="toc-items">{this.innerItems.map((item) => renderTOCItem(item))}</div>
{this.innerItems.map((item) => this.renderItem(item))}
</Host>
);
}
Expand Down
6 changes: 0 additions & 6 deletions core/src/components/toc-item/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,10 @@
### Used by

- [la-table-of-contents](../table-of-contents)
- [la-toc-item](.)

### Depends on

- [la-toc-item](.)

### Graph
```mermaid
graph TD;
la-toc-item --> la-toc-item
la-table-of-contents --> la-toc-item
style la-toc-item fill:#f9f,stroke:#333,stroke-width:4px
```
Expand Down
15 changes: 3 additions & 12 deletions core/src/components/toc-item/toc-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class TocItem {
render() {
const isParent = !!this.item.children?.length;
const showItem = !this.filteredItems || this.filteredItems.has(this.item);
const url = this.item.url || `#${this.item.id || ''}`;
const href = this.item.href || `#${this.item.id || ''}`;

const renderToggleBtnInner = () => {
if (this.expanded) {
Expand All @@ -100,22 +100,13 @@ export class TocItem {
<div class="content">
<div class="content__action">
{this.prependHtml ? <div class="content__action__prepend" innerHTML={this.prependHtml}></div> : null}
<a href={url} class="content__action__title" onClick={this.onItemTitleClick}>
<a href={href} class="content__action__title" onClick={this.onItemTitleClick}>
{this.item.title}
</a>
{this.appendHtml ? <div class="content__action__append" innerHTML={this.appendHtml}></div> : null}
</div>
<div class="content__children">
{this.item.children?.length
? this.item.children.map((item: TOCItem) => (
<la-toc-item
item={item}
filteredItems={this.filteredItems}
expandIconHtml={this.expandIconHtml}
collapseIconHtml={this.collapseIconHtml}
></la-toc-item>
))
: null}
<slot />
</div>
</div>
</Host>
Expand Down

0 comments on commit de4bab8

Please sign in to comment.