v1.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <?php
  2. namespace zin;
  3. require_once dirname(__DIR__) . DS . 'tabpane' . DS . 'v1.php';
  4. class tabs extends wg
  5. {
  6. /**
  7. * @var mixed[]
  8. */
  9. protected static $defineProps = array(
  10. /* Tabs direction: h - horizontal, v - vertical */
  11. 'direction?:string="h"',
  12. 'collapse?: bool=false',
  13. 'headerClass?:string=""',
  14. 'navClass?:string=""',
  15. 'titleClass?:string="font-bold text-md"'
  16. );
  17. public static function getPageCSS()
  18. {
  19. return <<<CSS
  20. .tabs-header {position: relative; z-index: 1}
  21. .tabs-nav>.nav-item>a {padding: 0; padding-right: 0; color: var(--color-gray-800);}
  22. .tabs-nav>.nav-item>a:after {border-width: 0;}
  23. .tabs-nav>.nav-item>a:before {background: none;}
  24. .tabs-nav>.nav-item>a.active {color: var(--color-primary-500);}
  25. .tabs-nav>.nav-item>a.active:after {border-bottom-color: var(--color-primary-500) !important; border-bottom-width: 2px;}
  26. .tabs-nav>.divider {height: 20px; border-right: 1px solid #DDD;}
  27. .tabs-collapse-btn {position: absolute; top: 0; right: 0; width: 24px; height: 24px;}
  28. .tab-content {padding-top: 10px;}
  29. CSS;
  30. }
  31. /**
  32. * @param \zin\tabPane $tabPane
  33. * @param string $titleClass
  34. */
  35. protected function buildTitleView($tabPane, $titleClass = "")
  36. {
  37. $key = $tabPane->prop('key');
  38. $title = $tabPane->prop('title');
  39. $active = $tabPane->prop('active');
  40. $hide = $tabPane->prop('hide');
  41. $param = $tabPane->prop('param');
  42. $prefix = $tabPane->block('prefix');
  43. $suffix = $tabPane->block('suffix');
  44. $navClass = $this->prop('navClass');
  45. return li
  46. (
  47. setClass('nav-item', $navClass, $hide ? 'hidden' : ''),
  48. setData('key', $key),
  49. a
  50. (
  51. set('data-toggle', 'tab'),
  52. set('data-param', $param),
  53. setClass('font-medium', $active ? 'active' : null, $titleClass),
  54. set::href("#$key"),
  55. $prefix,
  56. span($title),
  57. $suffix
  58. )
  59. );
  60. }
  61. /**
  62. * @param array $titleViews
  63. * @return node
  64. */
  65. protected function buildTabHeader($titleViews)
  66. {
  67. $isVertical = $this->prop('direction') === 'v';
  68. $collapse = $this->prop('collapse');
  69. $headerClass = $this->prop('headerClass');
  70. return div
  71. (
  72. setClass('tabs-header bg-white'),
  73. ul
  74. (
  75. setClass('tabs-nav nav nav-tabs gap-x-5', $collapse ? 'relative' : null, $headerClass),
  76. $isVertical ? setClass('nav-stacked') : null,
  77. $titleViews
  78. ),
  79. $this->buildCollapseBtn()
  80. );
  81. }
  82. /**
  83. * @param array $titleViews
  84. * @return node
  85. * @param mixed[] $contentViews
  86. */
  87. protected function buildTabBody($contentViews)
  88. {
  89. return div
  90. (
  91. setClass('tab-content'),
  92. $contentViews
  93. );
  94. }
  95. private function processTabs()
  96. {
  97. $tabPanes = array();
  98. $children = array();
  99. $hasActived = false;
  100. foreach ($this->children() as $child)
  101. {
  102. if($child instanceof tabPane)
  103. {
  104. $tabPanes[] = $child;
  105. if($child->prop('active')) $hasActived = true;
  106. continue;
  107. }
  108. $children[] = $child;
  109. }
  110. if(!$hasActived && !empty($tabPanes)) $tabPanes[0]->setProp('active', true);
  111. return array($tabPanes, $children);
  112. }
  113. private function buildCollapseBtn()
  114. {
  115. $collapse = $this->prop('collapse');
  116. if(!$collapse) return null;
  117. return collapseBtn
  118. (
  119. setClass('tabs-collapse-btn'),
  120. set::target('.tab-content'),
  121. set::parent('.tabs')
  122. );
  123. }
  124. protected function build()
  125. {
  126. $isVertical = $this->prop('direction') === 'v';
  127. $titleClass = $this->prop('titleClass');
  128. list($tabPanes, $children) = $this->processTabs();
  129. $titleViews = array();
  130. foreach($tabPanes as $tabPane)
  131. {
  132. $titleViews[] = $this->buildTitleView($tabPane, $titleClass);
  133. if($tabPane->prop('divider')) $titleViews[] = div(set::className('divider'));
  134. }
  135. return div
  136. (
  137. setClass('tabs', $isVertical ? 'flex' : null),
  138. set($this->getRestProps()),
  139. $this->buildTabHeader($titleViews),
  140. $this->buildTabBody($tabPanes),
  141. $children
  142. );
  143. }
  144. }